एक क्वेरी को सॉर्ट करने के अच्छे तरीके? - Django


111

मैं यह करने की कोशिश कर रहा हूं:

  • उच्चतम स्कोर के साथ 30 लेखक प्राप्त करें ( Author.objects.order_by('-score')[:30])

  • लेखकों को आदेश दें last_name


कोई सुझाव?


4
@ आरएच: तो सही समाधान के रूप में एलेक्समार्टेली के जवाब की जांच करने के बारे में कैसे? (ऐसा नहीं है कि उसे किसी और प्रतिनिधि की जरूरत है, जब तक कि वह उस स्कीट आदमी के बाद नहीं जा रहा है ...)
पॉलएमसीजी

जवाबों:


190

व्हाट अबाउट

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विधि का उपयोग करके प्रति-क्वेरीसेट आधार पर इसे ओवरराइड कर सकते हैं ।

उदाहरण:

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

ऊपर परिणाम scoreअवरोही, तो last_nameआरोही द्वारा आदेश दिया जाएगा । "-score"अवरोही क्रम के सामने नकारात्मक संकेत इंगित करता है। आरोही क्रम निहित है।


1
@ एलेक्स: ग्रैजी एलेक्स! यह बहुत अच्छा था, मैं ऑपरेटर मॉड्यूल के बारे में पढ़ना चाहता हूँ!
रेडिएंटहैक्स

3
क्या यह Author.objects.order_by ('- स्कोर', 'last_name') [: 30] की तुलना में अधिक कुशल है?
ब्रायन लुफ्ट

4
@ ब्रायन - यदि "अधिक कुशल" से आपका मतलब है "अधिक सही" तो हां, इसका। :) आपका समाधान लेखकों को स्कोर द्वारा बहुत अधिक क्रमबद्ध रखता है, और केवल उसी स्कोर के साथ उन लेखकों को वर्णानुक्रम में रखता है (जो कि द्वितीयक कुंजी कैसे काम करती है)। एलेक्स दिखाता है कि परिणाम कैसे लें, और फिर उनके लिए एक पूरी तरह से अलग तरह का आदेश लागू करें (प्रति-कुंजी कुंजी अभिव्यक्ति को परिभाषित करने के लिए key = oper.attrgetter का उपयोग करके), जो कि ओपी ने पूछा है।
पॉलएमसीजी

@Paul: यह नहीं है कि मैंने क्या पूछा, हालांकि एलेक्स का जवाब सही है!
रेडिएंटहैक्स

4
क्यों नहीं कर रहे हैं छँटाई कुंजी समारोह lambda x: x.last_name? यह छोटा है, अधिक क्रिया है और किसी भी आयात की आवश्यकता नहीं है।
क्रिज़ीस्तोफ़ स्यूलरज़

12

मैं केवल यह वर्णन करना चाहता था कि अंतर्निहित समाधान (एसक्यूएल-ओनली) हमेशा सबसे अच्छे नहीं होते हैं। पहले तो मैंने सोचा कि क्योंकि 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)

जैसा कि आप देख सकते हैं कि यह पहले वाले के समान परिणाम है, जिसका अर्थ है कि यह काम नहीं करेगा जैसा कि आप उम्मीद करेंगे।


13
आपका परिणाम # 3 स्कोर द्वारा नीचे उतर रहा है और फिर last_name IFF द्वारा किसी भी ऑब्जेक्ट का समान स्कोर है। समस्या यह है कि आपके परिणाम सेट में कोई भी वस्तु समान स्कोर नहीं है, इसलिए केवल '-score' क्रम क्रम को प्रभावित कर रहा है। 487 तक 3 लेखक स्कोर सेट करने का प्रयास करें और # 3 फिर से चलाएँ।
1

हाँ, मैं समझता हूँ कि मैं वास्तव में केवल यह बताना चाहता था कि अंतर्निहित समाधान (एसक्यूएल-ओनली) हमेशा सर्वश्रेष्ठ नहीं होते हैं।
jathanism

3
इसने ठीक वही किया जिसकी मुझे उम्मीद थी: लेक्सिकोग्राफिक ऑर्डरिंग (जो थोड़े से छोटी है अगर पहली छँटाई कुंजी सभी अलग है)।
जोनास कोल्कर

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 से अधिक लेखक प्राप्त कर सकते हैं और min(30,author_count)क्या आपके पास 30 से कम लेखक हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.