Django क्वेरी में OR स्थिति कैसे करें?


294

मैं इस SQL ​​क्वेरी के बराबर एक Django क्वेरी लिखना चाहता हूं:

SELECT * from user where income >= 5000 or income is NULL.

Django क्वेरी फ़िल्टर का निर्माण कैसे करें?

User.objects.filter(income__gte=5000, income=0)

यह काम नहीं करता है, क्योंकि यह ANDफिल्टर है। मैं ORव्यक्तिगत क्वेरी के मिलन के लिए फ़िल्टर करना चाहता हूं ।


जवाबों:


548
from django.db.models import Q
User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True))

प्रलेखन के माध्यम से


यदि आप ऑब्जेक्ट का प्रिंट जोड़ते हैं तो यह मदद करेगा। इसलिए हम ORM और Query दोनों आउटपुट को इससे परिचित कर सकते हैं। BTW महान उदाहरण।
एडविन पाज़

क्या इस प्रकार के क्वेरी का उपयोग करना बेहतर है या दो अलग-अलग प्रश्न करना है?
MHB

60

क्योंकि क्वेरीज़ पायथन __or__ऑपरेटर ( |), या यूनियन को लागू करता है, यह सिर्फ काम करता है। आपकी अपेक्षा से कम के रूप में, |द्विआधारी ऑपरेटर एक रिटर्न QuerySetतो order_by(), .distinct()और अन्य क्वेरीसमूह फिल्टर अंत पर हमला बोला जा सकता है।

combined_queryset = User.objects.filter(income__gte=5000) | User.objects.filter(income__isnull=True)
ordered_queryset = combined_queryset.order_by('-income')

अपडेट 2019-06-20: यह अब पूरी तरह से Django 2.1 QuerySet API संदर्भ में प्रलेखित है । अधिक ऐतिहासिक चर्चा DjangoProject टिकट # 21333 में पाई जा सकती है ।


18
"अनिर्धारित" और "विरासत" मुझे डराते हैं। मुझे लगता है कि यह क्यू ऑब्जेक्ट का उपयोग करने के लिए सुरक्षित है, जैसा कि यहां स्वीकृत उत्तर में विस्तृत है।
जमान

2
FYI करें, order_by () और अलग () को पाइप किए गए
क्वेरीसेट पर

@carruthd धन्यवाद मैंने भी इसकी पुष्टि की। विल संपादित
hobs

क्या प्रत्येक व्यक्ति के लिए order_by () लागू किया जा सकता है और फिर संयुक्त हो सकता है? ताकि प्रत्येक हालत के लिए आदेश अभी भी बनाए रखा है? उदाहरण के लिए, joint_queryset = User.objects.filter (income__gte = 5000) .order_by ('आय') | User.objects.filter (income__lt = 5000) .order_by ('- आय')?
डेडलॉक

2
@Oatman: | ऑपरेटर प्रलेखित है। Docs.djangoproject.com/en/2.0/ref/models/querysets देखें : "सामान्य तौर पर, Q () ऑब्जेक्ट्स शर्तों को परिभाषित करना और पुन: उपयोग करना संभव बनाते हैं। यह उपयोग करने वाले जटिल डेटाबेस क्वेरीज़ के निर्माण की अनुमति देता है (OR) और (() और) ऑपरेटर्स; विशेष रूप से, या OR का उपयोग करना संभव नहीं है। मैंने पहले के संस्करणों के लिए प्रलेखन की जांच नहीं की थी लेकिन पाइप ऑपरेटर Django 1.1.4 से कम से कम काम करता है (बस कोशिश की गई)।
मेकरू

10

मौजूदा विकल्पों में दोनों विकल्प पहले से ही उल्लिखित हैं:

from django.db.models import Q
q1 = User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True))

तथा

q2 = User.objects.filter(income__gte=5000) | User.objects.filter(income__isnull=True)

हालाँकि, कुछ भ्रम की स्थिति है, जिसके बारे में किसी को पसंद करना है।

मुद्दा यह है कि वे एसक्यूएल स्तर पर समान हैं , इसलिए आपको जो भी पसंद है , उसे लेने के लिए स्वतंत्र महसूस करें!

Django ORM कुकबुक इस बारे में कुछ विस्तार से बात करती है, यहाँ प्रासंगिक हिस्सा है:


queryset = User.objects.filter(
        first_name__startswith='R'
    ) | User.objects.filter(
    last_name__startswith='D'
)

फलस्वरूप होता है

In [5]: str(queryset.query)
Out[5]: 'SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login",
"auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name",
"auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff",
"auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user"
WHERE ("auth_user"."first_name"::text LIKE R% OR "auth_user"."last_name"::text LIKE D%)'

तथा

qs = User.objects.filter(Q(first_name__startswith='R') | Q(last_name__startswith='D'))

फलस्वरूप होता है

In [9]: str(qs.query)
Out[9]: 'SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login",
 "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name",
  "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff",
  "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user"
  WHERE ("auth_user"."first_name"::text LIKE R% OR "auth_user"."last_name"::text LIKE D%)'

स्रोत: django-orm-cookbook


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