Django - क्वेरी परिणामों को सीमित करना


200

मैं एक मॉडल के अंतिम 10 उदाहरण लेना चाहता हूं और यह कोड है:

 Model.objects.all().order_by('-id')[:10]

क्या यह सच है कि सबसे पहले सभी उदाहरणों को उठाएं, और फिर केवल 10 अंतिम बार लें? क्या कोई और प्रभावी तरीका है?


जवाबों:


304

Django क्वेरीज़ आलसी हैं। इसका मतलब है कि एक क्वेरी केवल डेटाबेस से टकराएगी जब आप विशेष रूप से परिणाम के लिए पूछेंगे।

इसलिए जब तक आप प्रिंट नहीं करते हैं या वास्तव में एक क्वेरी के परिणाम का उपयोग करते हैं, जिसे आप बिना डेटाबेस एक्सेस के आगे फ़िल्टर कर सकते हैं।

जैसा कि आप अपने कोड के नीचे देख सकते हैं कि केवल अंतिम 10 वस्तुओं को लाने के लिए केवल एक वर्ग क्वेरी निष्पादित करता है।

In [19]: import logging                                 
In [20]: l = logging.getLogger('django.db.backends')    
In [21]: l.setLevel(logging.DEBUG)                      
In [22]: l.addHandler(logging.StreamHandler())      
In [23]: User.objects.all().order_by('-id')[:10]          
(0.000) SELECT "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."password", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."last_login", "auth_user"."date_joined" FROM "auth_user" ORDER BY "auth_user"."id" DESC LIMIT 10; args=()
Out[23]: [<User: hamdi>]

मैंने इसे mongoDB पर आज़माया और यह कहता है कि SELECT समर्थित नहीं है। MongoDB पर यह कैसे करें?
5

@winux चूंकि यह Django- विशिष्ट है, ऐसा लगता है कि आपको विशेष रूप से Mongo / NoSQL-type डेटाबेस के साथ काम करने के लिए Django की स्थापना करने की आवश्यकता है। यह मेरे अनुभव में एक विशिष्ट सेटअप नहीं है, मानक Django ORM सेटअप के संबंध में।
बेनामी कायर

38

वास्तव में मुझे लगता LIMIT 10है कि डेटाबेस को जारी किया जाएगा ताकि पाइथन में स्लाइसिंग डेटाबेस में न हो।

देखें सीमित-क्वेरीसमूहों अधिक जानकारी के लिए।


ध्यान दें कि यह क्वेरीज़ के लिए काम नहीं करेगा जिसे फ़िल्टर करने की भी आवश्यकता है, क्योंकि आप स्लाइस करने के बाद फ़िल्टर नहीं कर सकते।
माइक 'पोमैक्स' कमेरमन्स

2
इसलिए इसे स्लाइस करने से पहले छान लें। लिंक के लिए धन्यवाद स्वाद!
व्याचेज़

13

ऐसा लगता है कि प्रश्न में हल अब Django 1.7 के साथ काम नहीं करता है और एक त्रुटि उठाता है: "एक स्लाइस लेने के बाद क्वेरी को फिर से चालू नहीं कर सकता है"

दस्तावेज़ के अनुसार https://docs.djangoproject.com/en/dev/topics/db/queries/#limiting-querysets पायथन स्लाइस सिंटैक्स के "स्टेप" पैरामीटर को बाध्य करते हुए क्वेरी का मूल्यांकन करता है। यह इस तरह से काम करता है:

Model.objects.all().order_by('-id')[:10:1]

फिर भी मुझे आश्चर्य है कि अगर SQL या Python स्लाइस में लिमिट निष्पादित हो जाती है तो पूरा रिजल्ट सरणी वापस आ जाती है। स्मृति को लागू करने के लिए विशाल सूचियों को पुनः प्राप्त करने के लिए कोई अच्छा नहीं है।


यहां तक ​​कि यह समाधान django> = 1.8 परीक्षण के साथ काम नहीं करता है।
sonus21

3

हाँ। यदि आप वस्तुओं का एक सीमित सबसेट प्राप्त करना चाहते हैं, तो आप नीचे दिए गए कोड के साथ कर सकते हैं:

उदाहरण:

obj=emp.objects.all()[0:10]

शुरुआत 0 वैकल्पिक है, इसलिए

obj=emp.objects.all()[:10]

उपरोक्त कोड पहले 10 उदाहरण देता है।


1

अन्य उपयोगी उत्तरों के अतिरिक्त और अवलोकन के रूप में, यह ध्यान देने योग्य है कि [:10]स्लाइसिंग के रूप में वास्तव में कर रहे हैं सूची के पहले 10 तत्वों को वापस कर देंगे। , न कि अंतिम 10 ...

अंतिम 10 प्राप्त करने के लिए आपको [-10:]इसके बजाय ( यहां देखें ) करना चाहिए । यह आपको तत्वों को उलटने के लिए उपयोग order_by('-id')करने से बचने में मदद करेगा -


1
मैंने यह कोशिश की और "नकारात्मक अनुक्रमण समर्थित नहीं है।"
19

@DarkCygnus Product.objects.filter(~Q(price=0))[-5:]मुझे एक ही त्रुटि का कारण बनता है: "नकारात्मक अनुक्रमण समर्थित नहीं है।"
बर्सम

यह किसी क्वेरी पर django में काम नहीं करता है: code.djangoproject.com/ticket/13089 यदि आप क्वेरी को किसी सूची में परिवर्तित करते हैं तो यह काम करेगा।
वलीम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.