Django में खाली क्वेरी के लिए जाँच


183

जाँच करने के लिए अनुशंसित मुहावरा क्या है कि कोई प्रश्न किसी परिणाम पर लौटा है?
उदाहरण:

orgs = Organisation.objects.filter(name__iexact = 'Fjuk inc')
# If any results
    # Do this with the results without querying again.
# Else, do something else...

मुझे लगता है कि यह जाँचने के कई अलग-अलग तरीके हैं, लेकिन मैं जानना चाहता हूँ कि एक अनुभवी Django उपयोगकर्ता यह कैसे करेगा। डॉक्स में अधिकांश उदाहरण केवल उस मामले को अनदेखा करते हैं जहां कुछ भी नहीं मिला था ...

जवाबों:


207
if not orgs:
    # Do this...
else:
    # Do that...

5
उदाहरण के लिए, प्रलेखन में भी इसे प्राथमिकता दी जा सकती है: docs.djangoproject.com/en/1.8/topics/http/shortcuts/#id7
Wtower

1
@Wtower कोड को आप 404 जुटाने के लिए अनुबंध के लिए संदर्भित करते हैं यदि फ़िल्टरिंग अभिव्यक्ति कोई रिकॉर्ड नहीं मारती है या रिकॉर्ड listहोने पर परिणाम का एक उत्पादन करने के लिए । वहां कोड केवल एक बार डेटाबेस को हिट करेगा। यदि वे उपयोग करते हैं exist()या count()पहले जांचते हैं कि क्या रिकॉर्ड वापस होने वाले हैं, तो वे डेटाबेस को दो बार मारेंगे (एक बार जांच करने के लिए, एक बार रिकॉर्ड प्राप्त करने के लिए)। यह एक विशिष्ट स्थिति है। यह सामान्य स्थिति में प्रवेश नहीं करता है , यह जानने के लिए पसंदीदा तरीका है कि कोई क्वेरी रिकॉर्ड वापस करेगी या नहींif queryset:...
लुइस

1
@ मैं जिस कोड का उल्लेख करता हूं वह केवल एक उदाहरण है कि इसमें यह if not my_objects:प्रदर्शित करने के लिए एक पंक्ति है कि यह डॉक्स में ऐसा कैसे करता है। बाकी सब बिलकुल अप्रासंगिक है इसलिए मुझे आपकी बात नहीं आती। वे एक हजार प्रश्न बना सकते थे और यह अभी भी पूरी तरह से अप्रासंगिक होगा क्योंकि यह इस उत्तर का बिंदु नहीं है, जिसके साथ मैं स्पष्ट करता हूं कि मैं सहमत हूं।
Wtower

1
@Wtower यह केवल इस बात का स्पष्टीकरण है कि कैसे get_object_or_404काम करता है, यह जाँचने का एक पसंदीदा तरीका नहीं है कि कोई तत्व किसी क्वेरी में मौजूद है या नहीं। एक क्वेरी पर डूइंग लिस्ट () प्रत्येक ऑब्जेक्ट को एक क्वेरीसेट पर लाएगा, जो कि दो बार क्वेरी करने से भी बदतर होगा अगर बहुत सारी पंक्तियाँ वापस आ गईं।
माइनमैक्सगव

1
अधिक विस्तृत उत्तर के लिए नीचे दिए गए उत्तर पर @ leonid-shvechikov का उपयोग करें: .exists()यदि qs का मूल्यांकन नहीं होने जा रहा है, तो इसका उपयोग अधिक कुशल है।
18'18

191

संस्करण 1.2 के बाद से, Django में QuerySet है। मौजूद है () विधि जो सबसे कुशल है:

if orgs.exists():
    # Do this...
else:
    # Do that...

लेकिन अगर आप वैसे भी QuerySet का मूल्यांकन करने जा रहे हैं तो इसका उपयोग करना बेहतर है:

if orgs:
   ...

अधिक जानकारी के लिए QuerySet.exists () प्रलेखन पढ़ें


.exists () केवल .filter () के लिए है, क्या .get () के लिए कुछ है?
रोल करें

.getएक क्वेरी को वापस नहीं करता है। यह एक वस्तु देता है। तो उसके लिए Google
Aseem

यदि आपके पास एक बड़ी क्वेरी है तो यह केवल अधिक कुशल है: docs.djangoproject.com/en/2.1/ref/models/querysets/#exists
नाथन जोन्स

16

यदि आपके पास बड़ी संख्या में ऑब्जेक्ट हैं, तो यह (कई बार) बहुत तेज़ हो सकता है:

try:
    orgs[0]
    # If you get here, it exists...
except IndexError:
    # Doesn't exist!

एक परियोजना पर मैं एक विशाल डेटाबेस के साथ काम कर रहा हूं, not orgs400+ ms है और orgs.count()250ms है। मेरे सबसे आम उपयोग के मामलों में (जहां परिणाम हैं), इस तकनीक को अक्सर 20ms से कम हो जाता है। (एक मामला मुझे मिला, यह 6. था)

बहुत अधिक समय हो सकता है, ज़ाहिर है, इस पर निर्भर करता है कि डेटाबेस को परिणाम खोजने के लिए कितनी दूर देखना होगा। या इससे भी तेज, अगर यह जल्दी से मिल जाए; YMMV।

संपादित करें: यह होगा अक्सर की तुलना में धीमी हो orgs.count()अगर परिणाम नहीं मिला है, खासकर अगर हालत आप पर फ़िल्टर कर रहे हैं एक दुर्लभ एक है; परिणामस्वरूप, यह देखने के कार्यों में विशेष रूप से उपयोगी है, जहां आपको यह सुनिश्चित करने की आवश्यकता है कि दृश्य मौजूद है या Http404 फेंकें। (जहां, एक को उम्मीद होगी, लोग उन यूआरएल के लिए पूछ रहे हैं जो अधिक से अधिक बार मौजूद हैं।)


10

किसी क्वेरी की शून्यता की जांच करने के लिए:

if orgs.exists():
    # Do something

या आप किसी क्वेरी में पहले आइटम की जांच कर सकते हैं, अगर यह मौजूद नहीं है तो यह वापस आ जाएगी None:

if orgs.first():
    # Do something

7
if orgs.exists()एक उत्तर द्वारा कवर किया गया था जो इस से लगभग 5 साल पहले प्रदान किया गया था। केवल एक चीज यह जवाब तालिका में लाती है जो शायद नया है if orgs.first()। (यहां तक ​​कि यह बहस का मुद्दा है: क्या यह लगभग 5 साल पहले orgs[0] सुझाए गए कार्यों को करने से काफी अलग है?) आपको जवाब के उस हिस्से को विकसित करना चाहिए: जब कोई पहले प्रस्तावित अन्य समाधानों के बजाय ऐसा करना चाहेगा ?
लुइस

9

सबसे कुशल तरीका (django 1.2 से पहले) यह है:

if orgs.count() == 0:
    # no results
else:
    # alrigh! let's continue...

5
.exists () और भी अधिक कुशल लगता है
dzida

5
सिवाय इसके .exists () को मेरी टिप्पणी के कुछ महीने बाद जोड़ा गया था, और Django 1.2 (जिसमें एपीआई शामिल है) को ~ 8 महीने बाद जारी किया गया था। लेकिन डाउन-वोटिंग के लिए धन्यवाद और तथ्यों को जांचने की जहमत नहीं उठानी चाहिए।
बार्टोज़

4
क्षमा करें, मैंने इसे और अधिक सटीक और सकारात्मक रूप से मतदान करने के लिए आपके उत्तर में छोटा सा संपादन जोड़ा।
dzida

4

मैं विधेय से असहमत हूं

if not orgs:

यह होना चाहिए

if not orgs.count():

मैं काफी बड़े परिणाम सेट (~ 150k परिणाम) के साथ एक ही मुद्दा रहा था। ऑपरेटर को क्वेरीसेट में अधिभारित नहीं किया गया है, इसलिए परिणाम वास्तव में चेक से पहले सूची के रूप में अनपैक किया गया है। मेरे मामले में निष्पादन का समय तीन आदेशों से कम हो गया।


6
__nonzero__ पहले से ही QuerySet में ओवरलोडेड है। यदि परिणाम कैश नहीं किया गया है (यह क्वेरी के पहले उपयोग पर कभी नहीं है) तो __nonzero__ का व्यवहार क्वेरीसेट के सभी तत्वों पर पुनरावृति करना है। यह बहुत बुरा है अगर सेट बड़ा है।
हेडलेरोस

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