2010-03-09 23 views
69

什麼,我試圖做的是這樣的:排序查詢集的好方法? - Django的

  • 通過last_name


得到30名與作者得分最高( Author.objects.order_by('-score')[:30]

  • 順序作者

    有什麼建議嗎?

  • +2

    @RH:那麼如何檢查AlexMartelli的答案是正確的解決方案?(並不是說他需要更多的代表,除非他追求那個Skeet傢伙......) – PaulMcG 2010-03-10 01:42:00

    +0

    簡單而重要。這工作。謝謝! – Shilpa 2016-08-27 13:31:21

    回答

    125

    什麼

    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返回的結果是通過在模型中的元的ordering選項給出的排序元組排序。您可以通過使用order_by方法在基於每個QuerySet的基礎上覆蓋此值。

    實施例:

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

    結果上述將由score降序由last_name升序排序,然後。 "-score"前的負號表示降序。暗示升序。

    +0

    @Alex:grazie alex!那真是太好了,我正在閱讀關於操作員模塊的內容! – RadiantHex 2010-03-09 21:52:35

    +3

    這是否比Author.objects.order_by(' - score','last_name')[:30]更高效? – 2010-03-10 00:45:59

    +4

    @布萊恩 - 如果用「更高效」的意思是「更正確」,那麼是的,它的。 :)你的解決方案使得作者幾乎按照分數排序,並且只能按照相同分數(這是次要密鑰的工作方式)來使這些作者字母化。 Alex展示瞭如何獲取結果,然後對它們應用完全不同的排序順序(使用key = operator.attrgetter來定義每個對象的關鍵表達式),這是OP要求的。 – PaulMcG 2010-03-10 01:39:22

    3

    這是一種允許關閉分數的方法。

    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多個作家這種方式和min(30,author_count)有櫃面你有少於30名作者。

    9

    我只是想說明內置解決方案(僅限於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) 
    

    使用亞歷馬爾泰利的解決方案,準確地提供了前5人通過last_name排序:

    >>> 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) 
    

    正如你可以看到它是相同的結果作爲第一位的,這意味着它不工作,你會Ë xpect。

    +10

    您的結果#3按排序降序排列,然後按last_name排序IFF任何對象都有相同的分數。問題是結果集中沒有任何對象具有相同的分數,因此只有'-score'影響排序順序。嘗試設置3個作者的分數爲487並再次運行#3。 – istruble 2010-03-10 01:52:05

    +0

    是的,我明白這一點。我只是想說明內置解決方案(僅限於SQL)並不總是最好的解決方案。 – jathanism 2010-03-10 14:24:21

    +0

    +1違反直覺的ORDER BY子句的好例子 – PaulMcG 2010-03-10 17:12:52