खोज…


परिचय

एक F () अभिव्यक्ति Django के लिए पायथन मेमोरी में मान खींचने के लिए बिना डेटाबेस में मॉडल फ़ील्ड या एनोटेट कॉलम के मूल्य को संदर्भित करने के लिए पायथन ऑब्जेक्ट का उपयोग करने का एक तरीका है। यह डेवलपर्स को कुछ निश्चित दौड़ की स्थितियों से बचने और मॉडल फ़ील्ड मूल्यों के आधार पर परिणामों को फ़िल्टर करने की अनुमति देता है।

वाक्य - विन्यास

  • django.db.models से F आयात करें

दौड़ की स्थिति से बचना

यदि आपको पता नहीं है कि दौड़ की स्थिति क्या है, तो यह प्रश्नोत्तर देखें।

निम्नलिखित कोड दौड़ की स्थिति के अधीन हो सकते हैं:

article = Article.objects.get(pk=69)
article.views_count += 1
article.save()

यदि views_count 1337 बराबर है, तो इसका परिणाम इस प्रकार होगा:

UPDATE app_article SET views_count = 1338 WHERE id=69

यदि दो क्लाइंट एक ही समय में इस लेख का उपयोग करते हैं, तो ऐसा क्या हो सकता है कि पहला HTTP article.save() Article.objects.get(pk=69) निष्पादित करने से पहले दूसरा HTTP अनुरोध article.save() . article.save() निष्पादित करता है। इस प्रकार, दोनों अनुरोधों में views_count = 1337 , इसे views_count = 1338 और डेटाबेस में views_count = 1338 को views_count = 1338 , जबकि यह वास्तव में 1339 होना चाहिए।

इसे ठीक करने के लिए, F() अभिव्यक्ति का उपयोग करें:

article = Article.objects.get(pk=69)
article.views_count = F('views_count') + 1
article.save()

दूसरी ओर, इसके परिणामस्वरूप ऐसी क्वेरी होगी:

UPDATE app_article SET views_count = views_count + 1 WHERE id=69

बल्क में क्वेरीसेट अपडेट कर रहा है

मान लेते हैं कि हम लेखक के सभी लेखों से आईडी 51 साथ 2 अपवोट निकालना चाहते हैं।
केवल पायथन के साथ ऐसा करने से N क्वेरीज़ को निष्पादित किया जाएगा ( N क्वेरी में लेखों की संख्या होने के नाते):

for article in Article.objects.filter(author_id=51):
    article.upvotes -= 2
    article.save()
    # Note that there is a race condition here but this is not the focus
    # of this example.

क्या होगा अगर पायथन में सभी लेखों को खींचने के बजाय, उन पर लूपिंग करना, उत्थान को कम करना, और प्रत्येक अपडेट किए गए डेटाबेस को वापस सहेजना, एक और तरीका था?
एक F() अभिव्यक्ति का उपयोग करना, इसे एक क्वेरी में कर सकते हैं:

Article.objects.filter(author_id=51).update(upvotes=F('upvotes') - 2)

जिसे निम्नलिखित SQL क्वेरी में अनुवादित किया जा सकता है:

UPDATE app_article SET upvotes = upvotes - 2 WHERE author_id = 51

यह बेहतर क्यों है?

  • पायथन काम करने के बजाय, हम उस डेटाबेस में लोड को पारित करते हैं जो इस तरह के प्रश्न करने के लिए ठीक है।
  • वांछित परिणाम प्राप्त करने के लिए आवश्यक डेटाबेस प्रश्नों की संख्या में प्रभावी रूप से कटौती की जाती है।

खेतों के बीच अंकगणित संचालन निष्पादित करें

मॉडल क्षेत्रों के बीच अंकगणित संचालन ( + , - , * आदि) को निष्पादित करने के लिए F() अभिव्यक्तियों का उपयोग किया जा सकता है ताकि उनके बीच बीजगणितीय लुकअप / कनेक्शन को परिभाषित किया जा सके।

  • मॉडल होने दें:

    class MyModel(models.Model):
        int_1 = models.IntegerField()
        int_2 = models.IntegerField()
    
  • अब मान लेते हैं कि हम MyModel तालिका की सभी वस्तुओं को पुनः प्राप्त करना चाहते हैं, जो int_1 और int_2 फ़ील्ड्स इस समीकरण को संतुष्ट करती हैं: int_1 + int_2 >= 5annotate() का उपयोग annotate() और filter() हमें मिलता है:

    result = MyModel.objects.annotate(
                 diff=F(int_1) + F(int_2)
             ).filter(diff__gte=5)
    

    result अब पूर्वोक्त सभी वस्तुएँ हैं।

हालांकि उदाहरण Integer क्षेत्रों का उपयोग करता है, यह विधि हर क्षेत्र पर काम करेगी जिस पर एक अंकगणितीय ऑपरेशन लागू किया जा सकता है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow