मैं Django क्वेरी में OR फ़िल्टर कैसे करूं?


303

मैं उन वस्तुओं को सूचीबद्ध करना चाहता हूं जो या तो एक उपयोगकर्ता ने जोड़े हैं (वे निर्माता के रूप में सूचीबद्ध हैं) या आइटम को अनुमोदित किया गया है।

इसलिए मुझे मूल रूप से चयन करने की आवश्यकता है:

item.creator = owner or item.moderated = False

मैं Django में यह कैसे करूंगा? (अधिमानतः एक फिल्टर या क्वेरीसेट के साथ)।

जवाबों:


544

ऐसी Qवस्तुएँ हैं जो जटिल लुकअप की अनुमति देती हैं। उदाहरण:

from django.db.models import Q

Item.objects.filter(Q(creator=owner) | Q(moderated=False))

6
यह कैसे प्रोग्रामेटिक रूप से किया जा सकता है? इसलिए, उदाहरण के लिएfor f in filters: Item.objects.filter(Q(creator=f1) | Q(creator=f2) | ...)
एलेक्सिस

14
@AlexisK reduce(lambda q, f: q | Q(creator=f), filters, Q())बिग क्यू ऑब्जेक्ट बनाने के लिए कुछ का उपयोग करें ।
फोब अगे

24
@alexis: आप भी कर सकते हैं Item.objects.filter(creator__in=creators), उदाहरण के लिए।
केविन लंदन

4
यदि आप सोच रहे हैं (मेरे जैसा) जहां |OR ऑपरेटर के रूप में उपयोग किया जा रहा है, तो यह वास्तव में सेट यूनियन ऑपरेटर है। इसे बिटवाइज के रूप में भी इस्तेमाल किया जाता है (या यहाँ नहीं): stackoverflow.com/questions/5988665/pipe-character-in-python
e100

124

आप उपयोग कर सकते हैं | ऑपरेटर क्यू वस्तुओं की आवश्यकता के बिना क्वेरी को सीधे संयोजित करने के लिए:

result = Item.objects.filter(item.creator = owner) | Item.objects.filter(item.moderated = False)

(संपादित करें - मैं शुरू में अनिश्चित था अगर इससे अतिरिक्त क्वेरी हुई लेकिन @spookylukey ने बताया कि आलसी क्वेरीसेट मूल्यांकन का ध्यान रखता है)


4
यह पता लगाने के लिए कि दिए गए अनुरोध पर कौन से प्रश्नों का निष्पादन किया जाता है, आप डिबग-टूलबार Django एप्लिकेशन का उपयोग कर सकते हैं। यह कमाल और जीत से बना है।
डेनिज डोगन

25
'django.db इंपोर्ट कनेक्शन से' करें और 'connection.queries' का उपयोग करें। इसके लिए DEBUG = True की आवश्यकता है। BTW, आपको पता होना चाहिए कि QuerySets आलसी हैं और यह सिर्फ एक बार DB को हिट करता है।
स्पूकीलुकि

1
नकारात्मक तुलना के साथ बाहर रखा जा सकता है?
Neob91

2
क्या यह परिणाम के डुप्लिकेट में डुप्लिकेट हो सकता है?
चार्ल्स हारो

1
अधिक विशेष रूप से क्वेरी सेट केवल DB को हिट करने के लिए होते हैं, जब आप उन्हें अनुक्रमित करने का प्रयास करते हैं, अन्यथा आप केवल एक क्वेरी का निर्माण कर रहे हैं।
जाबे

41

यह ध्यान देने योग्य है कि क्यू अभिव्यक्तियों को जोड़ना संभव है ।

उदाहरण के लिए:

from django.db.models import Q

query = Q(first_name='mark')
query.add(Q(email='mark@test.com'), Q.OR)
query.add(Q(last_name='doe'), Q.AND)

queryset = User.objects.filter(query)

यह एक प्रश्न के साथ समाप्त होता है जैसे:

(first_name = 'mark' or email = 'mark@test.com') and last_name = 'doe'

इस तरह से कोई से निपटने के लिए की जरूरत है या ऑपरेटरों, को कम करने के आदि


2
लेकिन यह लिखना आसान है query |= Q(email='mark@test.com')?
एलेक्स78191 2

26

आप फ़िल्टर को गतिशील बनाना चाहते हैं तो आपको लैम्ब्डा का उपयोग करना होगा

from django.db.models import Q

brands = ['ABC','DEF' , 'GHI']

queryset = Product.objects.filter(reduce(lambda x, y: x | y, [Q(brand=item) for item in brands]))

reduce(lambda x, y: x | y, [Q(brand=item) for item in brands]) के बराबर है

Q(brand=brands[0]) | Q(brand=brands[1]) | Q(brand=brands[2]) | .....

6
मेरे लिए बिल्कुल सही जवाब! पायथन 3 के लिए, from functools import reduceपहले से करें।
धर्मित

1
के operator.or_बजाय का उपयोग क्यों नहीं lambda x, y: x | y?
2:78 बजे एलेक्स78191

20

पुराने उत्तर के समान, लेकिन थोड़ा सा सरल, लंबोदर के बिना:

filter_kwargs = {
    'field_a': 123,
    'field_b__in': (3, 4, 5, ),
}

इन दो स्थितियों को फ़िल्टर करने के लिए OR:

Item.objects.filter(Q(field_a=123) | Q(field_b__in=(3, 4, 5, ))

कार्यक्रम के समान परिणाम प्राप्त करने के लिए:

list_of_Q = [Q(**{key: val}) for key, val in filter_kwargs.items()]
Item.objects.filter(reduce(operator.or_, list_of_Q))

(यहाँ दो लाइनों में टूट गया, स्पष्टता के लिए)

operatorमानक पुस्तकालय में है: import operator
docstring से:

or_ (a, b) - समान | ख।

पायथन 3 के लिए, बिल्टिन reduceनहीं है , लेकिन अभी भी मानक पुस्तकालय में है:from functools import reduce


पुनश्च

यह सुनिश्चित करने के लिए मत भूलें कि list_of_Qखाली नहीं है - reduce()खाली सूची पर चोक होगा, इसे कम से कम एक तत्व की आवश्यकता है।


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