排序查询集的好方法? - Django

时间:2010-03-09 21:37:57

标签: python django django-models

我想要做的是:

  • 获得得分最高的30位作者(Author.objects.order_by('-score')[:30]

  • last_name

  • 排序作者

有什么建议吗?

3 个答案:

答案 0 :(得分:157)

怎么样?
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(*字段)

默认情况下,QuerySet返回的结果按模型Meta中ordering选项给出的排序元组排序。您可以使用order_by方法在每个QuerySet的基础上覆盖它。

示例:

ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]

上面的结果将按score降序排序,然后按last_name升序排序。 "-score"前面的负号表示降序。升序是隐含的。

答案 1 :(得分:11)

我只是想说明内置解决方案(仅限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)

正如您所看到的,它与第一个结果相同,这意味着它不能像您期望的那样工作。

答案 2 :(得分:5)

这是一种允许与截止分数联系的方式。

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)