Django 2.1 - Conditional Expressions

सशर्त अभिव्यक्तियाँ




django

सशर्त अभिव्यक्तियाँ

सशर्त अभिव्यक्तियों को आप उपयोग करते हैं if ... elif ... फिल्टर, एनोटेशन, एकत्रीकरण और अपडेट के भीतर else तर्क। एक सशर्त अभिव्यक्ति एक तालिका की प्रत्येक पंक्ति के लिए स्थितियों की एक श्रृंखला का मूल्यांकन करती है और मिलान परिणाम अभिव्यक्ति लौटाती है। सशर्त अभिव्यक्तियों को भी जोड़ा जा सकता है और अन्य expressions तरह घोंसला बनाया जा सकता है।

सशर्त अभिव्यक्ति कक्षाएं

हम निम्नलिखित उदाहरणों में निम्नलिखित मॉडल का उपयोग करेंगे:

from django.db import models

class Client(models.Model):
    REGULAR = 'R'
    GOLD = 'G'
    PLATINUM = 'P'
    ACCOUNT_TYPE_CHOICES = (
        (REGULAR, 'Regular'),
        (GOLD, 'Gold'),
        (PLATINUM, 'Platinum'),
    )
    name = models.CharField(max_length=50)
    registered_on = models.DateField()
    account_type = models.CharField(
        max_length=1,
        choices=ACCOUNT_TYPE_CHOICES,
        default=REGULAR,
    )

When

class When(condition=None, then=None, **lookups) [source]

A When() ऑब्जेक्ट का उपयोग किसी शर्त को एन्कैप्सुलेट करने के लिए किया जाता है और इसके परिणाम को सशर्त अभिव्यक्ति में उपयोग के लिए। When() ऑब्जेक्ट का उपयोग filter() विधि का उपयोग करने के समान है। फ़ील्ड लुकअप या Q ऑब्जेक्ट का उपयोग करके स्थिति को निर्दिष्ट किया जा सकता है। परिणाम then कीवर्ड का उपयोग करके प्रदान किया जाता है।

कुछ उदाहरण:

>>> from django.db.models import F, Q, When
>>> # String arguments refer to fields; the following two examples are equivalent:
>>> When(account_type=Client.GOLD, then='name')
>>> When(account_type=Client.GOLD, then=F('name'))
>>> # You can use field lookups in the condition
>>> from datetime import date
>>> When(registered_on__gt=date(2014, 1, 1),
...      registered_on__lt=date(2015, 1, 1),
...      then='account_type')
>>> # Complex conditions can be created using Q objects
>>> When(Q(name__startswith="John") | Q(name__startswith="Paul"),
...      then='name')

ध्यान रखें कि इनमें से प्रत्येक मान एक अभिव्यक्ति हो सकता है।

ध्यान दें

चूँकि then कीवर्ड तर्क When() के परिणाम के लिए आरक्षित है, यदि किसी Model नाम पर कोई फ़ील्ड है then एक संभावित विरोध है। इसे दो तरीकों से हल किया जा सकता है:

>>> When(then__exact=0, then=1)
>>> When(Q(then=0), then=1)

Case

class Case(*cases, **extra) [source]

एक Case() अभिव्यक्ति की तरह है if ... elif ... else Python में बयान। प्रदत्त प्रत्येक condition में When() वस्तुओं का मूल्यांकन क्रम में किया जाता है, जब तक कि कोई व्यक्ति सत्य मूल्य का मूल्यांकन नहीं करता है। When() ऑब्जेक्ट वापस किया जाता है When() मिलान से result अभिव्यक्ति।

एक सरल उदाहरण:

>>>
>>> from datetime import date, timedelta
>>> from django.db.models import Case, CharField, Value, When
>>> Client.objects.create(
...     name='Jane Doe',
...     account_type=Client.REGULAR,
...     registered_on=date.today() - timedelta(days=36))
>>> Client.objects.create(
...     name='James Smith',
...     account_type=Client.GOLD,
...     registered_on=date.today() - timedelta(days=5))
>>> Client.objects.create(
...     name='Jack Black',
...     account_type=Client.PLATINUM,
...     registered_on=date.today() - timedelta(days=10 * 365))
>>> # Get the discount for each Client based on the account type
>>> Client.objects.annotate(
...     discount=Case(
...         When(account_type=Client.GOLD, then=Value('5%')),
...         When(account_type=Client.PLATINUM, then=Value('10%')),
...         default=Value('0%'),
...         output_field=CharField(),
...     ),
... ).values_list('name', 'discount')
<QuerySet [('Jane Doe', '0%'), ('James Smith', '5%'), ('Jack Black', '10%')]>

Case() किसी भी संख्या को स्वीकार करता है When() वस्तुओं को व्यक्तिगत तर्क के रूप में। कीवर्ड तर्क का उपयोग करके अन्य विकल्प प्रदान किए जाते हैं। यदि कोई भी स्थिति TRUE मूल्यांकन नहीं करती है, तो default कीवर्ड तर्क के साथ दी गई अभिव्यक्ति वापस आ जाती है। यदि कोई default तर्क प्रदान None किया जाता है, तो None भी उपयोग None किया जाता है।

यदि हम Client साथ कितने समय के लिए छूट के आधार पर अपनी पिछली क्वेरी को बदलना चाहते हैं, तो हम लुकअप का उपयोग करके ऐसा कर सकते हैं:

>>> a_month_ago = date.today() - timedelta(days=30)
>>> a_year_ago = date.today() - timedelta(days=365)
>>> # Get the discount for each Client based on the registration date
>>> Client.objects.annotate(
...     discount=Case(
...         When(registered_on__lte=a_year_ago, then=Value('10%')),
...         When(registered_on__lte=a_month_ago, then=Value('5%')),
...         default=Value('0%'),
...         output_field=CharField(),
...     )
... ).values_list('name', 'discount')
<QuerySet [('Jane Doe', '5%'), ('James Smith', '0%'), ('Jack Black', '10%')]>

ध्यान दें

याद रखें कि परिस्थितियों का मूल्यांकन क्रम में किया जाता है, इसलिए उपरोक्त उदाहरण में हमें सही परिणाम मिलता है भले ही दूसरी स्थिति जेन डो और जैक ब्लैक दोनों से मेल खाती हो। यह एक तरह से काम करता है जैसे if elif else बयान Python

Case() filter() क्लॉज में भी काम करता है। उदाहरण के लिए, सोने के ग्राहकों को खोजने के लिए जो एक महीने से अधिक समय से पंजीकृत हैं और प्लैटिनम ग्राहक जो एक साल से अधिक समय पहले पंजीकृत हुए हैं:

>>> a_month_ago = date.today() - timedelta(days=30)
>>> a_year_ago = date.today() - timedelta(days=365)
>>> Client.objects.filter(
...     registered_on__lte=Case(
...         When(account_type=Client.GOLD, then=a_month_ago),
...         When(account_type=Client.PLATINUM, then=a_year_ago),
...     ),
... ).values_list('name', 'account_type')
<QuerySet [('Jack Black', 'P')]>

उन्नत प्रश्न

सशर्त अभिव्यक्तियों का उपयोग एनोटेशन, एकत्रीकरण, लुकअप और अपडेट में किया जा सकता है। उन्हें अन्य अभिव्यक्तियों के साथ भी जोड़ा जा सकता है। इससे आप शक्तिशाली सशर्त प्रश्न बना सकते हैं।

सशर्त अद्यतन

मान लें कि हम अपने ग्राहकों के लिए उनकी पंजीकरण तिथियों के मिलान के लिए account_type बदलना चाहते हैं। हम सशर्त अभिव्यक्ति और update() विधि का उपयोग करके ऐसा कर सकते हैं:

>>> a_month_ago = date.today() - timedelta(days=30)
>>> a_year_ago = date.today() - timedelta(days=365)
>>> # Update the account_type for each Client from the registration date
>>> Client.objects.update(
...     account_type=Case(
...         When(registered_on__lte=a_year_ago,
...              then=Value(Client.PLATINUM)),
...         When(registered_on__lte=a_month_ago,
...              then=Value(Client.GOLD)),
...         default=Value(Client.REGULAR)
...     ),
... )
>>> Client.objects.values_list('name', 'account_type')
<QuerySet [('Jane Doe', 'G'), ('James Smith', 'R'), ('Jack Black', 'P')]>

सशर्त एकत्रीकरण

यदि हम यह पता लगाना चाहते हैं कि प्रत्येक account_type कितने ग्राहक हैं? हम इसे प्राप्त करने के लिए कुल कार्यों के filter तर्क का उपयोग कर सकते हैं:

>>> # Create some more Clients first so we can have something to count
>>> Client.objects.create(
...     name='Jean Grey',
...     account_type=Client.REGULAR,
...     registered_on=date.today())
>>> Client.objects.create(
...     name='James Bond',
...     account_type=Client.PLATINUM,
...     registered_on=date.today())
>>> Client.objects.create(
...     name='Jane Porter',
...     account_type=Client.PLATINUM,
...     registered_on=date.today())
>>> # Get counts for each value of account_type
>>> from django.db.models import Count
>>> Client.objects.aggregate(
...     regular=Count('pk', filter=Q(account_type=Client.REGULAR)),
...     gold=Count('pk', filter=Q(account_type=Client.GOLD)),
...     platinum=Count('pk', filter=Q(account_type=Client.PLATINUM)),
... )
{'regular': 2, 'gold': 1, 'platinum': 3}

यह एग्रीगेट उस डेटाबेस पर SQL 2003 FILTER WHERE सिंटैक्स के साथ एक क्वेरी पैदा करता है जो इसका समर्थन करते हैं:

SELECT count('id') FILTER (WHERE account_type=1) as regular,
       count('id') FILTER (WHERE account_type=2) as gold,
       count('id') FILTER (WHERE account_type=3) as platinum
FROM clients;

अन्य डेटाबेस पर, यह CASE कथन का उपयोग करके अनुकरण किया जाता है:

SELECT count(CASE WHEN account_type=1 THEN id ELSE null) as regular,
       count(CASE WHEN account_type=2 THEN id ELSE null) as gold,
       count(CASE WHEN account_type=3 THEN id ELSE null) as platinum
FROM clients;

दो SQL स्टेटमेंट कार्यात्मक रूप से समतुल्य हैं लेकिन अधिक स्पष्ट FILTER बेहतर प्रदर्शन कर सकते हैं।