我想做的是:
获得得分最高的 30 位作者( Author.objects.order_by('-score')[:30] )
按姓氏排序作者
有什么建议么?
关于什么
import operator
auths = Author.objects.order_by('-score')[:30]
ordered = sorted(auths, key=operator.attrgetter('last_name'))
在 Django 1.4 和更新版本中,您可以通过提供多个字段来进行排序。
参考:https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by
order_by(*fields)
默认情况下,QuerySet
返回的结果按模型元中 ordering
选项给出的排序元组排序。您可以使用 order_by
方法在每个 QuerySet 的基础上覆盖它。
例子:
ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]
上面的结果将按 score
降序排列,然后按 last_name
升序排列。 "-score"
前面的负号表示降序。升序是隐含的。
我只是想说明内置解决方案(仅限 SQL)并不总是最好的。起初我认为因为 Django 的 QuerySet.objects.order_by
方法接受多个参数,所以您可以轻松地将它们链接起来:
ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]
但是,它并不像您期望的那样工作。举个例子,首先是按分数排序的总统列表(选择前 5 位以便于阅读):
>>> auths = Author.objects.order_by('-score')[:5]
>>> for x in auths: print x
...
James Monroe (487)
Ulysses Simpson (474)
Harry Truman (471)
Benjamin Harrison (467)
Gerald Rudolph (464)
使用 Alex Martelli 的解决方案,该解决方案准确地提供了按 last_name
排序的前 5 名人员:
>>> for x in sorted(auths, key=operator.attrgetter('last_name')): print x
...
Benjamin Harrison (467)
James Monroe (487)
Gerald Rudolph (464)
Ulysses Simpson (474)
Harry Truman (471)
现在组合 order_by
调用:
>>> myauths = Author.objects.order_by('-score', 'last_name')[:5]
>>> for x in myauths: print x
...
James Monroe (487)
Ulysses Simpson (474)
Harry Truman (471)
Benjamin Harrison (467)
Gerald Rudolph (464)
如您所见,它与第一个结果相同,这意味着它无法按您的预期工作。
这是一种允许截止分数平局的方法。
author_count = Author.objects.count()
cut_off_score = Author.objects.order_by('-score').values_list('score')[min(30, author_count)]
top_authors = Author.objects.filter(score__gte=cut_off_score).order_by('last_name')
通过这种方式,您可能会在 top_authors 中获得超过 30 位作者,并且如果您的作者少于 30 位,min(30,author_count)
就会出现。
lambda x: x.last_name
?它更短,更详细,不需要任何导入。