2009-04-11 12 views
201

मैं django फ़िल्टर में "या" कैसे करूं।Django फ़िल्टर - या?

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

तो मैं मूल रूप से

item.creator = owner or item.moderated = False 
चयन करने की आवश्यकता सक्षम होना चाहते हैं

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

उत्तर

361

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

from django.db.models import Q 

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

कैसे कम क्या यह प्रोग्रामेटिक रूप से किया जा सकता है? तो, उदाहरण के लिए 'फिल्टर में एफ के लिए सक्षम होना चाहिए: Item.objects.filter (क्यू (निर्माता = एफ 1) | क्यू (निर्माता = एफ 2) | ...) ' – Alexis

+10

@AlexisK कुछ कम करें जैसे' कम करें (लैम्ब्डा क्यू , एफ: क्यू | क्यू (निर्माता = एफ), फिल्टर, क्यू()) 'बड़ी क्यू वस्तु बनाने के लिए। – Phob

+16

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

82

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

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

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

+4

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

+0

मैं इसे खोल से परीक्षण कर रहा था। क्या खोल से सीधे उपरोक्त रेखा के प्रश्नों का पता लगाने का कोई तरीका है? –

+21

'django.db आयात कनेक्शन से' करें और 'connection.queries' का उपयोग करें। इसके लिए DEBUG = True की आवश्यकता है। बीटीडब्ल्यू, आपको पता होना चाहिए कि [क्वेरीसेट आलसी हैं] (https://docs.djangoproject.com/en/dev/topics/db/queries/#querysets-are-lazy) और यह सिर्फ एक बार डीबी को हिट करता है। – spookylukey

16

आप चाहते हैं फिल्टर गतिशील बनाने के लिए तो आप की तरह

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]) | ..... 
के बराबर है
+4

मेरे लिए बिल्कुल सही जवाब! पायथन 3 के लिए, 'functools आयात से पहले' कम करें। – Dharmit

10

बड़े answera की तरह, लेकिन एक सा सरल, लैम्ब्डा के बिना:

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

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

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

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

ही परिणाम प्रोग्राम के रूप में प्राप्त करने के लिए

(स्पष्टता के लिए यहां दो पंक्तियों में टूटा हुआ)

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

or_ (ए, बी) - एक के रूप में एक ही | ख। from functools import reduce


पी.एस.:

python3 के लिए, को कम मानक पुस्तकालय में नहीं है

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

9

यह ध्यान रखें कि यह क्यू भाव जोड़ना संभव नहीं है लायक है हो सकता है।

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

from django.db.models import Q 

query = Q(first_name='mark') 
query.add(Q(email='[email protected]'), Q.OR) 
query.add(Q(last_name='doe'), Q.AND) 

queryset = Users.objects.filter(query) 

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

(first_name = 'mark' or email = '[email protected]') and last_name = 'doe' 

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

संबंधित मुद्दे