मैं Django क्वेरी फ़िल्टरिंग में बराबर नहीं कैसे करूं?


664

Django मॉडल QuerySets में, मैं देख रहा हूं कि तुलनात्मक मूल्यों के लिए एक __gtऔर है __lt, लेकिन क्या वहाँ एक __ne/ !=/ <>( नहर नहीं है ?)।

मैं एक बराबर का उपयोग करके फ़िल्टर करना चाहता हूं:

उदाहरण:

Model:
    bool a;
    int x;

मुझे चाहिए

results = Model.objects.exclude(a=true, x!=5)

!=सही सिंटैक्स नहीं है। मैंने कोशिश की __ne, <>

मैंने प्रयोग करके समाप्त किया:

results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)

75
क्या परिणाम = Model.objects.exclude (a = true) .filter (x = 5) ने काम किया है?
ह्यूगड्रोवन

3
@hughdbrown। नहीं, आपकी क्वेरी a=trueपहले सभी को शामिल करती है और फिर x=5शेष पर फ़िल्टर लागू करती है । इच्छित क्वेरी केवल a=trueऔर जिनके साथ आवश्यक थी x!=5। अंतर यह है कि सभी के साथ a=trueऔर x=5उन्हें भी फ़िल्टर किया जाता है।
मिशेल वैन जुइलेन

जवाबों:


689

शायद क्यू ऑब्जेक्ट्स इस समस्या के लिए मदद कर सकते हैं। मैंने उनका कभी उपयोग नहीं किया है लेकिन ऐसा लगता है कि वे सामान्य अजगर के भावों की तरह नकारात्मक और संयुक्त हो सकते हैं।

अद्यतन: मैंने अभी इसे आज़माया है, यह बहुत अच्छी तरह से काम करता है:

>>> from myapp.models import Entry
>>> from django.db.models import Q

>>> Entry.objects.filter(~Q(id = 3))

[<Entry: Entry object>, <Entry: Entry object>, <Entry: Entry object>, ...]

16
@ JCLeitão: अधिक सहज वाक्यविन्यास के लिए नीचे @ d4nt का उत्तर भी देखें ।
पॉल डी। वेट

610

आपकी क्वेरी में एक दोहरी नकारात्मक प्रतीत होती है, आप उन सभी पंक्तियों को बाहर करना चाहते हैं जहाँ x 5 नहीं है, इसलिए दूसरे शब्दों में आप सभी पंक्तियों को शामिल करना चाहते हैं जहाँ x IS 5. मेरा मानना ​​है कि यह चाल चलेगा।

results = Model.objects.filter(x=5).exclude(a=true)

आपके विशिष्ट प्रश्न का उत्तर देने के लिए, "नहीं के बराबर" है, लेकिन ऐसा शायद इसलिए है क्योंकि django में "फ़िल्टर" और "बहिष्कृत" दोनों तरीके उपलब्ध हैं ताकि आप हमेशा वांछित परिणाम प्राप्त करने के लिए तर्क दौर को स्विच कर सकें।


2
@ d4nt: मैं गलत हो सकता हूं, लेकिन मुझे लगता है कि क्वेरी होनी चाहिएresults = Model.objects.filter(a=true).exclude(x=5)
तरनजीत

1
@ तरणजीत: मुझे लगता है कि आपने मूल प्रश्न को गलत बताया है। d4nt का संस्करण सही है, क्योंकि ओपी (a = True) को बाहर करना चाहता था और x = 5 के बहिष्करण (यानी इसे शामिल करना) को नकारना चाहता था।
चक

3
मुझे लगता है कि यह गलत है क्योंकि एक उदाहरण (x = 4, a = false) को गलत तरीके से बाहर रखा जाएगा।
रेमकोगर्लिच

4
@danigosa यह सही नहीं लगता। मैंने अभी खुद यह कोशिश की थी, excludeऔर filterकॉल के क्रम ने कोई सार्थक अंतर नहीं किया। WHEREखंड में शर्तों का क्रम बदल जाता है, लेकिन यह कैसे मायने रखता है?
coredumperror

4
@danigosa को बाहर करने और फ़िल्टर करने का क्रम मायने नहीं रखता है।
EralpB

132

field=valueप्रश्नों में वाक्य रचना के लिए एक आशुलिपि है field__exact=value। यह कहना है कि Django पहचानकर्ताओं में क्वेरी क्षेत्रों पर क्वेरी ऑपरेटरों डालता है । Django निम्नलिखित ऑपरेटरों का समर्थन करता है:

exact
iexact
contains
icontains
in
gt
gte
lt
lte
startswith
istartswith
endswith
iendswith
range
year
month
day
week_day
isnull
search
regex
iregex

मुझे यकीन है कि डे वोग्ट के सुझाव और उपयोग के रूप में क्यू ऑब्जेक्ट्स के साथ इनका संयोजन करके filter()या exclude()जैसा कि जेसन बेकर सुझाव देते हैं कि आपको बिल्कुल वही मिलेगा जो आपको किसी भी संभावित क्वेरी के बारे में चाहिए।


धन्यवाद यह बहुत बढ़िया है। मैं इस तरह से कुछ tg=Tag.objects.filter(user=request.user).exclude(name__regex=r'^(public|url)$')काम करता था और यह काम करता है।
सुहैलव्स

@suhail, कृपया ध्यान रखें कि सभी डेटाबेस रेगेक्स सिंटैक्स का समर्थन नहीं करते हैं :)
Anoyz

2
मैं में icontains, iexactऔर "मामले की संवेदनशीलता पर ध्यान न दें" के लिए समान खड़ा है। यह "उलटा" के लिए नहीं है।
आइवी ग्रोइंग

यह ध्यान देने योग्य है कि जब आप exclude()कई शर्तों के साथ उपयोग कर रहे हैं , तो आप दोनों शर्तों के तहत परिणामों को बाहर करने के लिए ORऑपरेटर के साथ प्रस्ताव की रचना करना चाह सकते हैं , जैसे exclude(Q(field1__queryop1=value1) | Q(field2__queryop2=value2))
क्लैप्स

98

Django 1.7 के साथ कस्टम लुक बनाना आसान है। Django आधिकारिक दस्तावेज__ne में एक लुकअप उदाहरण है ।

आपको पहले लुकअप खुद बनाना होगा:

from django.db.models import Lookup

class NotEqual(Lookup):
    lookup_name = 'ne'

    def as_sql(self, qn, connection):
        lhs, lhs_params = self.process_lhs(qn, connection)
        rhs, rhs_params = self.process_rhs(qn, connection)
        params = lhs_params + rhs_params
        return '%s <> %s' % (lhs, rhs), params

फिर आपको इसे पंजीकृत करने की आवश्यकता है:

from django.db.models.fields import Field
Field.register_lookup(NotEqual)

और अब आप __neइस तरह से अपने प्रश्नों में लुकअप का उपयोग कर सकते हैं :

results = Model.objects.exclude(a=True, x__ne=5)

88

में Django 1.9 / 1.10 तीन विकल्प हैं।

  1. चेन excludeऔरfilter

    results = Model.objects.exclude(a=true).filter(x=5)
  2. Q()ऑब्जेक्ट और ऑपरेटर का उपयोग करें~

    from django.db.models import Q
    object_list = QuerySet.filter(~Q(a=True), x=5)
  3. कस्टम लुकअप फ़ंक्शन रजिस्टर करें

    from django.db.models import Lookup
    from django.db.models.fields import Field
    
    @Field.register_lookup
    class NotEqual(Lookup):
        lookup_name = 'ne'
    
        def as_sql(self, compiler, connection):
            lhs, lhs_params = self.process_lhs(compiler, connection)
            rhs, rhs_params = self.process_rhs(compiler, connection)
            params = lhs_params + rhs_params
            return '%s <> %s' % (lhs, rhs), params

    register_lookupडेकोरेटर में जोड़ा गया Django 1.8 और कस्टम हमेशा की तरह देखने के सक्षम बनाता है:

    results = Model.objects.exclude(a=True, x__ne=5)

1
object_list = QuerySet.filter (~ Q (a = True), x = 5): उन सभी शर्तों को रखने के लिए याद रखें, जिनमें Q के बाद Q शामिल नहीं है।
Bhumi सिंघल

1
@MichaelHoffmann: A) आप ~ Q का उपयोग करके बहिष्करण के बाद डेटा के एक छोटे सेट पर फ़िल्टर करेंगे ताकि अधिक कुशल हो। बी) शायद दूसरे तरीके के आसपास अनुक्रमण काम नहीं करता है .. डुन पता है .. डन याद है!
भूमि सिंघल

41

मॉडल के साथ, आप के साथ फ़िल्टर कर सकते हैं =, __gt, __gte, __lt, __lte, आप उपयोग नहीं कर सकते ne, !=या <>। हालाँकि, Q ऑब्जेक्ट का उपयोग करने पर आप बेहतर फ़िल्टरिंग प्राप्त कर सकते हैं।

आप चेनिंग से बच सकते हैं QuerySet.filter()और QuerySet.exlude()है, और इस का उपयोग करें:

from django.db.models import Q
object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')

24

लंबित डिजाइन निर्णय। इस बीच, उपयोग करेंexclude()

Django इश्यू ट्रैकर में उल्लेखनीय प्रविष्टि # 5763 है , जिसका शीर्षक "क्वेरीसेट में" बराबर नहीं "फ़िल्टर ऑपरेटर" है । यह उल्लेखनीय है क्योंकि (अप्रैल 2016 के अनुसार) यह "9 साल पहले खोला गया था" (जिआंगो पत्थर की उम्र में), "4 साल पहले बंद हुआ", और "5 महीने पहले बदल गया"।

चर्चा के माध्यम से पढ़ें, यह दिलचस्प है। मूल रूप से, कुछ लोगों का तर्क __neजोड़ा जाना चाहिए जबकि अन्य कहते हैं कि exclude()यह स्पष्ट है और इसलिए __ne इसे जोड़ा नहीं जाना चाहिए ।

(मैं पूर्व से सहमत हूं, क्योंकि उत्तरार्द्ध तर्क लगभग यह कहने के बराबर है कि पायथन के पास नहीं होना चाहिए !=क्योंकि यह पहले से ही है ==और not...)



18

आपको इसका उपयोग करना चाहिए filterऔर इसे excludeपसंद करना चाहिए

results = Model.objects.exclude(a=true).filter(x=5)

8

कोड का अंतिम बिट उन सभी वस्तुओं को बाहर कर देगा जहां x! = 5 और a सही है। इसे इस्तेमाल करे:

results = Model.objects.filter(a=False, x=5)

याद रखें, उपरोक्त लाइन में = साइन इन पैरामीटर को ए और पैरामीटर 5 को पैरामीटर एक्स को असाइन कर रहा है। यह समानता के लिए जाँच नहीं है। इस प्रकार, क्वेरी कॉल में प्रतीक! = का उपयोग करने का कोई तरीका नहीं है।


3
यह 100% एक ही बात नहीं है क्योंकि उन क्षेत्रों के लिए अशक्त मूल्य भी हो सकते हैं।
माइकएन

यह केवल उन वस्तुओं पर लौटता है जिनमें = गलत और x = 5 है, लेकिन प्रश्न में एक उदाहरण (a = false, x = 4) शामिल होगा।
रेमकोगर्लिच

1
results = Model.objects.filter(a__in=[False,None],x=5)
जेरेमी

8

परिणाम = Model.objects.filter (a = True) .exclude (x = 5)
इस वर्ग उत्पन्न करता है:
Tablex से * चुनें जहाँ a! = 0 और x! = 5 हो
Sql इस बात पर निर्भर करता है कि आपके True / False फ़ील्ड का प्रतिनिधित्व कैसे किया जाता है, और डेटाबेस इंजन। Django कोड आप सभी की जरूरत है, हालांकि है।



6

आप जिस चीज की तलाश कर रहे हैं, वह सभी वस्तुएं हैं जो a=false या तो हैं x=5। Django में, क्वेरीसेट के बीच ऑपरेटर के |रूप में कार्य करता है OR:

results = Model.objects.filter(a=false)|Model.objects.filter(x=5)

5

यह आपका वांछित परिणाम देगा।

from django.db.models import Q
results = Model.objects.exclude(Q(a=True) & ~Q(x=5))

बराबर नहीं के लिए आप ~एक समान क्वेरी पर उपयोग कर सकते हैं । स्पष्ट रूप से, Qसमान क्वेरी तक पहुंचने के लिए उपयोग किया जा सकता है।


कृपया संपादन जांचें; "और" का उपयोग करके, तर्क के रूप में Q(a=True) and ~Q(x=5)मूल्यांकन करेगा । कृपया पढ़ें: docs.python.org/3/reference/expressions.html#boolean-operations और docs.python.org/3/reference/…~Q(x=5).exclude
tzot

2

इस प्रश्न के बहुत सारे गलत उत्तरों के लिए बाहर देखें!

जेरार्ड का तर्क सही है, हालांकि यह एक क्वेरी के बजाय एक सूची लौटाएगा (जो कि कोई फर्क नहीं पड़ता)।

यदि आपको क्वेरी की आवश्यकता है, तो Q का उपयोग करें:

from django.db.models import Q
results = Model.objects.filter(Q(a=false) | Q(x=5))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.