Django 2.1 - Making queries

प्रश्न करना




django

प्रश्न करना

एक बार जब आप अपने डेटा मॉडल बना लेते हैं , तो Django आपको स्वचालित रूप से एक डेटाबेस-एब्स्ट्रैक्शन एपीआई देता है जो आपको ऑब्जेक्ट बनाने, पुनर्प्राप्त करने, अपडेट करने और हटाने की सुविधा देता है। यह दस्तावेज़ बताता है कि इस एपीआई का उपयोग कैसे किया जाए। सभी विभिन्न मॉडल लुकअप विकल्पों की पूरी जानकारी के लिए डेटा मॉडल संदर्भ देखें।

इस गाइड के दौरान (और संदर्भ में), हम निम्नलिखित मॉडलों का उल्लेख करेंगे, जिसमें एक वेबलॉग एप्लिकेशन शामिल है:

from django.db import models

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=200)
    email = models.EmailField()

    def __str__(self):
        return self.name

class Entry(models.Model):
    blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    authors = models.ManyToManyField(Author)
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()

    def __str__(self):
        return self.headline

वस्तुओं का निर्माण

पायथन ऑब्जेक्ट्स में डेटाबेस-टेबल डेटा का प्रतिनिधित्व करने के लिए, Django एक सहज ज्ञान युक्त प्रणाली का उपयोग करता है: एक मॉडल वर्ग डेटाबेस तालिका का प्रतिनिधित्व करता है, और उस वर्ग का एक उदाहरण डेटाबेस तालिका में एक विशेष रिकॉर्ड का प्रतिनिधित्व करता है।

एक ऑब्जेक्ट बनाने के लिए, मॉडल वर्ग के लिए कीवर्ड तर्कों का उपयोग करके इसे तत्काल करें, फिर डेटाबेस में इसे सहेजने के लिए कॉल करें save()

यह मानते हुए कि मॉडल mysite/blog/models.py फ़ाइल में रहते हैं, यहाँ एक उदाहरण है:

>>> from blog.models import Blog
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()

यह पर्दे के पीछे एक INSERT SQL स्टेटमेंट करता है। Django डेटाबेस को तब तक हिट नहीं करता जब तक आप स्पष्ट रूप से save()

save() विधि का कोई वापसी मान नहीं है।

यह भी देखें

save() यहाँ वर्णित नहीं के कई उन्नत विकल्प लेता है। पूर्ण विवरण के लिए save() लिए दस्तावेज़ देखें।

किसी एकल चरण में किसी ऑब्जेक्ट को बनाने और सहेजने के लिए, create() विधि का उपयोग करें।

वस्तुओं में परिवर्तन सहेजना

डेटाबेस में पहले से मौजूद किसी ऑब्जेक्ट में परिवर्तन सहेजने के लिए, save() उपयोग करें।

पहले से ही डेटाबेस में सहेजे गए Blog उदाहरण b5 को देखते हुए, यह उदाहरण अपना नाम बदलता है और डेटाबेस में अपना रिकॉर्ड अपडेट करता है:

>>> b5.name = 'New name'
>>> b5.save()

यह पर्दे के पीछे एक UPDATE SQL कथन करता है। Django डेटाबेस को तब तक हिट नहीं करता जब तक आप स्पष्ट रूप से save()

सेविंग ForeignKey और ManyToManyField फील्ड

ForeignKey फील्ड को अपडेट करना ठीक उसी तरह काम करता है जैसे सामान्य फील्ड को सेव करना - बस विचाराधीन फील्ड को राइट टाइप का ऑब्जेक्ट असाइन करना। यह उदाहरण एक Entry उदाहरण entry के blog विशेषता को अद्यतन करता है, यह मानते हुए कि Entry और Blog उपयुक्त उदाहरण पहले से ही डेटाबेस में सहेजे गए हैं (इसलिए हम उन्हें नीचे प्राप्त कर सकते हैं):

>>> from blog.models import Blog, Entry
>>> entry = Entry.objects.get(pk=1)
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()

एक ManyToManyField अपडेट करना थोड़ा अलग तरीके से काम करता है - संबंध पर रिकॉर्ड जोड़ने के लिए फ़ील्ड पर add() विधि का उपयोग करें। यह उदाहरण entry ऑब्जेक्ट में Author उदाहरण joe जोड़ता है:

>>> from blog.models import Author
>>> joe = Author.objects.create(name="Joe")
>>> entry.authors.add(joe)

एक बार में कई ManyToManyField में कई रिकॉर्ड जोड़ने के लिए, कॉल में कई तर्क शामिल करें add() , जैसे:

>>> john = Author.objects.create(name="John")
>>> paul = Author.objects.create(name="Paul")
>>> george = Author.objects.create(name="George")
>>> ringo = Author.objects.create(name="Ringo")
>>> entry.authors.add(john, paul, george, ringo)

Django शिकायत करेगा यदि आप गलत प्रकार के ऑब्जेक्ट को असाइन करने या जोड़ने का प्रयास करते हैं।

पुनः प्राप्त वस्तु

अपने डेटाबेस से वस्तुओं को पुनः प्राप्त करने के लिए, अपने मॉडल वर्ग पर एक Manager माध्यम से QuerySet निर्माण करें।

QuerySet आपके डेटाबेस से ऑब्जेक्ट्स के संग्रह का प्रतिनिधित्व करता है। इसमें शून्य, एक या कई फ़िल्टर हो सकते हैं । फ़िल्टर दिए गए मापदंडों के आधार पर क्वेरी परिणामों को कम करते हैं। SQL शब्दों में, एक QuerySet एक SELECT स्टेटमेंट की QuerySet , और एक फ़िल्टर एक सीमित खंड है जैसे कि WHERE या LIMIT

अपने मॉडल के Manager का उपयोग करके आपको एक QuerySet प्राप्त QuerySet है। प्रत्येक मॉडल में कम से कम एक Manager , और इसे डिफ़ॉल्ट रूप से objects कहा जाता है। इसे मॉडल वर्ग के माध्यम से सीधे एक्सेस करें, जैसे:

>>> Blog.objects
<django.db.models.manager.Manager object at ...>
>>> b = Blog(name='Foo', tagline='Bar')
>>> b.objects
Traceback:
    ...
AttributeError: "Manager isn't accessible via Blog instances."

ध्यान दें

Managers "तालिका-स्तरीय" संचालन और "रिकॉर्ड-स्तर" संचालन के बीच एक अलगाव को लागू करने के लिए, मॉडल उदाहरणों के बजाय केवल मॉडल कक्षाओं के माध्यम से सुलभ हैं।

एक मॉडल के लिए Manager QuerySets का मुख्य स्रोत है। उदाहरण के लिए, Blog.objects.all() एक QuerySet देता है जिसमें डेटाबेस में सभी Blog ऑब्जेक्ट होते हैं।

सभी वस्तुओं को पुनः प्राप्त करना

एक तालिका से वस्तुओं को पुनः प्राप्त करने का सबसे सरल तरीका उन सभी को प्राप्त करना है। ऐसा करने के लिए, Manager पर all() विधि का उपयोग करें:

>>> all_entries = Entry.objects.all()

all() विधि डेटाबेस में सभी ऑब्जेक्ट्स का QuerySet लौटाती है।

फ़िल्टर के साथ विशिष्ट वस्तुओं को पुनः प्राप्त करना

QuerySet all() द्वारा लौटाया गया है all() डेटाबेस तालिका में सभी वस्तुओं का वर्णन करता है। आमतौर पर, हालांकि, आपको वस्तुओं के पूर्ण सेट का केवल सबसेट का चयन करना होगा।

इस तरह के सबसेट को बनाने के लिए, आप प्रारंभिक QuerySet परिष्कृत करते हैं, फ़िल्टर शर्तों को जोड़ते हैं। QuerySet को परिष्कृत करने के दो सबसे आम तरीके हैं:

filter(**kwargs)
दिए गए लुकअप मापदंडों से मेल खाने वाली वस्तुओं से युक्त एक नया QuerySet लौटाता है।
exclude(**kwargs)
दिए गए लुकअप मापदंडों से मेल खाने वाली वस्तुओं से युक्त एक नया QuerySet लौटाता है।

लुकअप पैरामीटर (उपरोक्त फ़ंक्शन परिभाषाओं में **kwargs ) नीचे दिए गए फ़ील्ड लुकअप में वर्णित प्रारूप में होना चाहिए।

उदाहरण के लिए, वर्ष 2006 से ब्लॉग प्रविष्टियों का QuerySet प्राप्त करने के लिए, filter() जैसे filter() उपयोग करें:

Entry.objects.filter(pub_date__year=2006)

डिफ़ॉल्ट प्रबंधक वर्ग के साथ, यह निम्नानुसार है:

Entry.objects.all().filter(pub_date__year=2006)

छानने का काम

QuerySet को परिष्कृत करने का परिणाम स्वयं एक QuerySet , इसलिए एक साथ श्रृंखला परिशोधन संभव है। उदाहरण के लिए:

>>> Entry.objects.filter(
...     headline__startswith='What'
... ).exclude(
...     pub_date__gte=datetime.date.today()
... ).filter(
...     pub_date__gte=datetime.date(2005, 1, 30)
... )

यह डेटाबेस में सभी प्रविष्टियों का प्रारंभिक QuerySet लेता है, एक फिल्टर जोड़ता है, फिर एक बहिष्करण, फिर एक अन्य फ़िल्टर। अंतिम परिणाम एक QuerySet जिसमें सभी प्रविष्टियों के साथ एक शीर्षक है जो "क्या" से शुरू होता है, जिसे 30 जनवरी 2005 और वर्तमान दिन के बीच प्रकाशित किया गया था।

फ़िल्टर QuerySet गए QuerySet अद्वितीय हैं

हर बार जब आप किसी QuerySet परिशोधित QuerySet , तो आपको एक नया-नया QuerySet है, जो किसी भी तरह से पिछले QuerySet । प्रत्येक शोधन एक अलग और विशिष्ट QuerySet बनाता है जिसे संग्रहीत, उपयोग और पुन: उपयोग किया जा सकता है।

उदाहरण:

>>> q1 = Entry.objects.filter(headline__startswith="What")
>>> q2 = q1.exclude(pub_date__gte=datetime.date.today())
>>> q3 = q1.filter(pub_date__gte=datetime.date.today())

ये तीनों QuerySets अलग हैं। पहला एक आधार QuerySet जिसमें सभी प्रविष्टियाँ हैं जिनमें "क्या" से शुरू होने वाली शीर्षक है। दूसरा पहले का एक सबसेट है, जिसमें एक अतिरिक्त मानदंड है जो उन रिकॉर्ड्स को बाहर करता है जिनके pub_date आज या भविष्य में हैं। तीसरा, पहले का एक सबसेट है, एक अतिरिक्त मानदंड है जो केवल उन अभिलेखों का चयन करता है जिनके pub_date आज या भविष्य में हैं। प्रारंभिक QuerySet ( q1 ) शोधन प्रक्रिया से अप्रभावित है।

QuerySet s आलसी हैं

QuerySets आलसी हैं - QuerySet बनाने का कार्य किसी भी डेटाबेस गतिविधि को शामिल नहीं करता है। आप पूरे दिन एक साथ फिल्टर को स्टैक कर सकते हैं, और Django वास्तव में क्वेरी को तब तक नहीं चलाएगा जब तक कि QuerySet का मूल्यांकन नहीं किया जाता है । इस उदाहरण पर एक नज़र डालें:

>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
>>> print(q)

हालांकि यह तीन डेटाबेस हिट जैसा दिखता है, वास्तव में यह डेटाबेस को केवल एक बार हिट करता है, अंतिम पंक्ति ( print(q) ) पर। सामान्य तौर पर, QuerySet के परिणाम डेटाबेस से नहीं लिए QuerySet हैं, जब तक आप उनके लिए "पूछ" नहीं लेते हैं। जब आप करते हैं, तो डेटाबेस तक पहुँच कर QuerySet का मूल्यांकन किया जाता है। जब मूल्यांकन होता है, तो अधिक विवरण के लिए, देखें कि क्वेरीसेट का मूल्यांकन कब किया जाता है

प्राप्त get() साथ एक ही वस्तु get()

filter() आपको हमेशा एक QuerySet , भले ही केवल एक ही वस्तु क्वेरी से मेल खाती हो - इस मामले में, यह एक QuerySet जिसमें एकल तत्व होगा।

यदि आप जानते हैं कि केवल एक ही वस्तु है जो आपकी क्वेरी से मेल खाती है, तो आप एक Manager पर get() विधि का उपयोग कर सकते हैं जो सीधे वस्तु लौटाता है:

>>> one_entry = Entry.objects.get(pk=1)

आप किसी भी क्वेरी एक्सप्रेशन को filter() साथ filter() तरह उपयोग कर सकते हैं - फिर से, नीचे फ़ील्ड लुकअप देखें।

ध्यान दें कि get() का उपयोग get() और filter() का उपयोग get() बीच अंतर है get() [0] एक स्लाइस के साथ filter() । यदि क्वेरी से मेल खाने वाले कोई परिणाम नहीं हैं, get() एक DoesNotExist अपवाद DoesNotExist । यह अपवाद मॉडल वर्ग की एक विशेषता है जो क्वेरी पर किया जा रहा है - इसलिए ऊपर दिए गए कोड में, यदि 1 की प्राथमिक कुंजी के साथ कोई Entry ऑब्जेक्ट नहीं है, तो Django Entry.DoesNotExist

इसी तरह, Django शिकायत करेगा यदि एक से अधिक आइटम get() क्वेरी से मेल खाते हैं। इस स्थिति में, यह MultipleObjectsReturned को बढ़ाएगा, जो फिर से मॉडल वर्ग की एक विशेषता है।

अन्य QuerySet विधियाँ

जब आप डेटाबेस से ऑब्जेक्ट्स देखना चाहते हैं, तो अधिकांश समय आप all() , get() , filter() और exclude() का उपयोग करेंगे। हालाँकि, यह सब वहाँ से दूर है; सभी विभिन्न QuerySet विधियों की पूरी सूची के लिए क्वेरीसैट एपीआई संदर्भ देखें।

सीमित QuerySet

अपने QuerySet परिणामों की एक निश्चित संख्या तक सीमित करने के लिए पायथन के सरणी-स्लाइसिंग सिंटैक्स के सबसेट का उपयोग करें। यह SQL के LIMIT और OFFSET क्लॉज के बराबर है।

उदाहरण के लिए, यह पहले 5 ऑब्जेक्ट लौटाता है ( LIMIT 5 ):

>>> Entry.objects.all()[:5]

यह दसवीं वस्तुओं के माध्यम से छठा रिटर्न देता है ( OFFSET 5 LIMIT 5 ):

>>> Entry.objects.all()[5:10]

नकारात्मक अनुक्रमण (यानी Entry.objects.all()[-1] ) समर्थित नहीं है।

आमतौर पर, क्वेरी क्वेरी QuerySet करना एक नया QuerySet - यह क्वेरी का मूल्यांकन नहीं करता है। एक अपवाद यह है कि यदि आप पायथन स्लाइस सिंटैक्स के "स्टेप" पैरामीटर का उपयोग करते हैं। उदाहरण के लिए, यह वास्तव में पहले 10 के हर दूसरे ऑब्जेक्ट की एक सूची वापस करने के लिए क्वेरी को निष्पादित करेगा:

>>> Entry.objects.all()[:10:2]

कटा हुआ क्वेरी के आगे फ़िल्टरिंग या ऑर्डर करना अस्पष्ट प्रकृति के कारण निषिद्ध है कि यह कैसे काम कर सकता है।

एक सूची के बजाय एक ही वस्तु को पुनः प्राप्त करने के लिए (जैसे SELECT foo FROM bar LIMIT 1 ,) एक स्लाइस के बजाय एक सरल सूचकांक का उपयोग करें। उदाहरण के लिए, यह डेटाबेस में पहली Entry देता है, हेडलाइन द्वारा वर्णानुक्रम में प्रविष्टियाँ क्रमबद्ध करने के बाद:

>>> Entry.objects.order_by('headline')[0]

यह लगभग बराबर है:

>>> Entry.objects.order_by('headline')[0:1].get()

ध्यान दें, हालांकि, इनमें से पहला DoesNotExist को बढ़ाएगा, जबकि दूसरा DoesNotExist यदि कोई ऑब्जेक्ट दिए गए मानदंडों से मेल नहीं खाता है। अधिक जानकारी के लिए get() देखें।

फ़ील्ड लुकअप

फ़ील्ड लुकअप आप SQL SQL क्लॉज का मांस कैसे निर्दिष्ट करते हैं। वे QuerySet मेथड filter() , exclude() और get() कीवर्ड तर्क के रूप में निर्दिष्ट हैं।

मूल लुकअप कीवर्ड तर्क, field__lookuptype=value लेते हैं। (यह एक डबल-अंडरस्कोर है)। उदाहरण के लिए:

>>> Entry.objects.filter(pub_date__lte='2006-01-01')

निम्नलिखित एसक्यूएल में अनुवाद (मोटे तौर पर):

SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';

यह कैसे संभव है

पायथन में ऐसे कार्यों को परिभाषित करने की क्षमता है जो मनमाने नाम मानों को स्वीकार करते हैं जिनके नाम और मूल्यों का मूल्यांकन रनटाइम पर किया जाता है। अधिक जानकारी के लिए, आधिकारिक पायथन ट्यूटोरियल में कीवर्ड तर्क देखें।

लुकअप में निर्दिष्ट फ़ील्ड को मॉडल फ़ील्ड का नाम होना चाहिए। हालांकि एक अपवाद है, एक ForeignKey मामले में आप _id के साथ प्रत्यय वाले क्षेत्र का नाम निर्दिष्ट कर सकते हैं। इस मामले में, मूल्य पैरामीटर में विदेशी मॉडल की प्राथमिक कुंजी के कच्चे मूल्य को शामिल करने की उम्मीद है। उदाहरण के लिए:

>>> Entry.objects.filter(blog_id=4)

यदि आप एक अमान्य कीवर्ड तर्क पास करते हैं, तो लुकअप फ़ंक्शन TypeError बढ़ाएगा।

डेटाबेस एपीआई दो दर्जन लुकअप प्रकारों का समर्थन करता है; एक संपूर्ण संदर्भ फ़ील्ड लुकअप संदर्भ में पाया जा सकता है। आपको जो उपलब्ध है, उसका स्वाद देने के लिए, यहां उन कुछ सामान्य लुक के बारे में बताया गया है जिनका आप शायद उपयोग करेंगे:

exact

एक "सटीक" मैच। उदाहरण के लिए:

>>> Entry.objects.get(headline__exact="Cat bites dog")

इन लाइनों के साथ SQL उत्पन्न करेगा:

SELECT ... WHERE headline = 'Cat bites dog';

यदि आप एक लुकअप प्रकार प्रदान नहीं करते हैं - अर्थात, यदि आपके कीवर्ड तर्क में डबल अंडरस्कोर नहीं है - तो लुकअप प्रकार को exact माना जाता है।

उदाहरण के लिए, निम्नलिखित दो कथन समतुल्य हैं:

>>> Blog.objects.get(id__exact=14)  # Explicit form
>>> Blog.objects.get(id=14)         # __exact is implied

यह सुविधा के लिए है, क्योंकि exact लुकअप सामान्य मामला है।

iexact

केस-असंवेदनशील मैच। तो, प्रश्न:

>>> Blog.objects.get(name__iexact="beatles blog")

"Beatles Blog" , "beatles blog" , या यहां तक ​​कि "BeAtlES blOG" "beatles blog" शीर्षक वाले Blog से मेल "BeAtlES blOG"

contains

केस-संवेदी नियंत्रण परीक्षण। उदाहरण के लिए:

Entry.objects.get(headline__contains='Lennon')

मोटे तौर पर इस एसक्यूएल में अनुवाद:

SELECT ... WHERE headline LIKE '%Lennon%';

ध्यान दें कि यह शीर्षक 'Today Lennon honored' नहीं बल्कि 'today lennon honored'

वहाँ भी एक मामले असंवेदनशील संस्करण है, icontains

startswith, endswith
क्रमशः खोज के साथ शुरू और समाप्त होता है। केस-असंवेदनशील संस्करण भी हैं जिन्हें istartswith और iendswith कहा जाता है।

फिर, यह केवल सतह को खरोंच करता है। एक संपूर्ण संदर्भ फ़ील्ड लुकअप संदर्भ में पाया जा सकता है।

लुकअप जो रिश्तों को फैलाते हैं

Django लुक्स में रिश्तों को "फॉलो" करने का एक शक्तिशाली और सहज तरीका प्रदान करता है, जो कि आप के लिए SQL JOIN s का ख्याल रखते हुए, पर्दे के पीछे से अपने आप हो जाता है। संबंध बनाने के लिए, बस मॉडल से संबंधित फ़ील्ड के फ़ील्ड नाम का उपयोग करें, जो डबल अंडरस्कोर द्वारा अलग किया गया है, जब तक कि आप अपने इच्छित फ़ील्ड तक नहीं पहुंच जाते।

यह उदाहरण एक Blog साथ सभी Entry ऑब्जेक्ट को पुनः प्राप्त करता है जिसका name 'Beatles Blog' :

>>> Entry.objects.filter(blog__name='Beatles Blog')

यह स्पैनिंग आप जितना चाहें उतना गहरा हो सकता है।

यह पीछे की ओर भी काम करता है। एक "रिवर्स" रिश्ते को संदर्भित करने के लिए, बस मॉडल के लोअरकेस नाम का उपयोग करें।

यह उदाहरण उन सभी Blog ऑब्जेक्ट्स को पुनः प्राप्त करता है जिनमें कम से कम एक Entry जिसकी headline में 'Lennon' :

>>> Blog.objects.filter(entry__headline__contains='Lennon')

यदि आप कई रिश्तों को फ़िल्टर कर रहे हैं और मध्यवर्ती मॉडल में से एक में कोई मान नहीं है जो फ़िल्टर स्थिति से मिलता है, तो Django इसे मान लेगा जैसे कि कोई खाली है (सभी मान NULL ), लेकिन वहां मान्य, ऑब्जेक्ट। इसका मतलब यह है कि कोई त्रुटि नहीं उठाई जाएगी। उदाहरण के लिए, इस फ़िल्टर में:

Blog.objects.filter(entry__authors__name='Lennon')

(यदि कोई संबंधित Author मॉडल था), यदि कोई author एक प्रविष्टि के साथ जुड़ा नहीं था, तो यह माना जाएगा कि लापता author की वजह से कोई त्रुटि होने के बजाय कोई name जुड़ा हुआ नहीं है। आमतौर पर यह वही होता है जो आप चाहते हैं। केवल मामला जहां यह भ्रामक हो सकता है यदि आप isnull का उपयोग कर रहे हैं। इस प्रकार:

Blog.objects.filter(entry__authors__name__isnull=True)

उन Blog ऑब्जेक्ट्स को वापस करेगा जिनके author पर एक खाली name और उन लोगों के लिए भी जिनके पास entry पर एक खाली author । यदि आप उन बाद वाली वस्तुओं को नहीं चाहते हैं, तो आप लिख सकते हैं:

Blog.objects.filter(entry__authors__isnull=False, entry__authors__name__isnull=True)

बहुआयामी रिश्तों का विस्तार

जब आप किसी ManyToManyField या एक रिवर्स ForeignKey आधार पर किसी ऑब्जेक्ट को फ़िल्टर कर रहे हैं, तो दो अलग-अलग प्रकार के फ़िल्टर हो सकते हैं, जिनमें आपकी रुचि हो सकती है। Blog / Entry संबंध पर विचार करें ( Blog to Entry is one-to-many relation)। हमें उन ब्लॉगों को खोजने में दिलचस्पी हो सकती है जिनके पास एक प्रविष्टि है जिसमें हेडलाइन में "लेनन" दोनों हैं और 2008 में प्रकाशित किया गया था। या हम उन ब्लॉगों को ढूंढना चाहते हैं जिनकी हेडलाइन में "लेनन" के साथ ही एक प्रविष्टि है 2008 में प्रकाशित किया गया था। चूंकि एक ही Blog जुड़ी कई प्रविष्टियां हैं, ये दोनों प्रश्न संभव हैं और कुछ स्थितियों में समझ में आते हैं।

उसी प्रकार की स्थिति एक ManyToManyField साथ उत्पन्न होती है। उदाहरण के लिए, यदि किसी Entry में कई ManyToManyField नामक tags , तो हम "म्यूजिक" और "बैंड्स" नामक टैग्स से जुड़ी प्रविष्टियां खोजना चाहते हैं या हम एक ऐसी प्रविष्टि चाहते हैं जिसमें "म्यूजिक" के नाम वाला टैग हो और एक स्टेटस "जनता"

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

यह थोड़ा भ्रमित करने वाला हो सकता है, इसलिए उम्मीद है कि एक उदाहरण स्पष्ट होगा। उन सभी ब्लॉगों का चयन करने के लिए, जिनमें शीर्षक में "लेनन" दोनों के साथ प्रविष्टियाँ हैं और जो 2008 में प्रकाशित हुई थीं (दोनों ही स्थितियों में एक ही प्रविष्टि संतोषजनक है), हम लिखेंगे:

Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)

उन सभी ब्लॉगों का चयन करने के लिए जिनमें हेडलाइन में "लेनन" के साथ एक प्रविष्टि है और साथ ही एक प्रविष्टि जो 2008 में प्रकाशित हुई थी, हम लिखेंगे:

Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)

मान लीजिए कि केवल एक ही ब्लॉग है जिसमें दोनों प्रविष्टियों में "लेनन" और 2008 से प्रविष्टियाँ थीं, लेकिन 2008 की प्रविष्टियों में से कोई भी "लेनन" नहीं थी । पहली क्वेरी किसी भी ब्लॉग को नहीं लौटाएगी, लेकिन दूसरी क्वेरी उस एक ब्लॉग को लौटा देगी।

दूसरे उदाहरण में, पहला फ़िल्टर उन सभी ब्लॉगों की क्वेरी को हेडलाइन में "लेनन" के साथ प्रविष्टियों से जुड़ा हुआ है। दूसरा फ़िल्टर उन ब्लॉग के सेट को आगे प्रतिबंधित करता है जो 2008 में प्रकाशित प्रविष्टियों से भी जुड़े होते हैं। दूसरे फ़िल्टर द्वारा चयनित प्रविष्टियाँ पहले फ़िल्टर में प्रविष्टियों के समान हो सकती हैं या नहीं भी हो सकती हैं। हम प्रत्येक फ़िल्टर स्टेटमेंट के साथ Blog आइटम फ़िल्टर कर रहे हैं, Entry आइटम नहीं।

ध्यान दें

बहु-मूल्य संबंधों को बढ़ाने वाले प्रश्नों के लिए filter() का व्यवहार, जैसा कि ऊपर वर्णित है, exclude() लिए समान रूप से लागू नहीं किया गया है exclude() । इसके बजाय, एक एकल exclude() कॉल में स्थितियां आवश्यक रूप से एक ही आइटम को संदर्भित नहीं करेंगी।

उदाहरण के लिए, निम्नलिखित क्वेरी उन ब्लॉगों को बाहर कर देगी, जिनमें 2008 में प्रकाशित शीर्षक और प्रविष्टियों में "लेनन" के साथ दोनों प्रविष्टियाँ शामिल हैं:

Blog.objects.exclude(
    entry__headline__contains='Lennon',
    entry__pub_date__year=2008,
)

हालांकि, filter() का उपयोग करते समय व्यवहार के विपरीत filter() , यह उन प्रविष्टियों पर आधारित ब्लॉग को सीमित नहीं करेगा जो दोनों स्थितियों को पूरा करते हैं। ऐसा करने के लिए, अर्थात उन सभी ब्लॉगों का चयन करने के लिए जिनमें "लेनन" के साथ प्रकाशित प्रविष्टियाँ नहीं हैं जो 2008 में प्रकाशित हुई थीं, आपको दो प्रश्न करने होंगे:

Blog.objects.exclude(
    entry__in=Entry.objects.filter(
        headline__contains='Lennon',
        pub_date__year=2008,
    ),
)

फ़िल्टर मॉडल पर फ़ील्ड्स को संदर्भित कर सकते हैं

अब तक दिए गए उदाहरणों में, हमने ऐसे फिल्टर का निर्माण किया है जो एक स्थिर के साथ एक मॉडल क्षेत्र के मूल्य की तुलना करते हैं। लेकिन क्या होगा यदि आप एक मॉडल फ़ील्ड के मूल्य की तुलना उसी मॉडल पर किसी अन्य फ़ील्ड के साथ करना चाहते हैं?

Django इस तरह की तुलना की अनुमति देने के लिए F expressions प्रदान करता है। F() उदाहरण F() एक क्वेरी के भीतर एक मॉडल क्षेत्र के संदर्भ के रूप में कार्य करते हैं। फिर इन संदर्भों को एक ही मॉडल उदाहरण पर दो अलग-अलग क्षेत्रों के मूल्यों की तुलना करने के लिए क्वेरी फिल्टर में उपयोग किया जा सकता है।

उदाहरण के लिए, उन सभी ब्लॉग प्रविष्टियों की सूची ढूंढने के लिए जो पिंगबैक से अधिक टिप्पणियां आई हैं, हम पिंगबैक गणना को संदर्भित करने के लिए एक F() ऑब्जेक्ट का निर्माण करते हैं, और क्वेरी में उस F() ऑब्जेक्ट का उपयोग करते हैं:

>>> from django.db.models import F
>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))

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

>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)

उन सभी प्रविष्टियों को खोजने के लिए जहां प्रविष्टि की रेटिंग पिंगबैक गणना और टिप्पणी गणना के योग से कम है, हम क्वेरी जारी करेंगे:

>>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))

F() ऑब्जेक्ट में संबंधों को जोड़ने के लिए आप डबल अंडरस्कोर नोटेशन का भी उपयोग कर सकते हैं। एक डबल अंडरस्कोर वाली F() ऑब्जेक्ट संबंधित ऑब्जेक्ट तक पहुंचने के लिए आवश्यक किसी भी जोड़ को पेश करेगा। उदाहरण के लिए, उन सभी प्रविष्टियों को पुनः प्राप्त करने के लिए जहां लेखक का नाम ब्लॉग नाम के समान है, हम क्वेरी जारी कर सकते हैं:

>>> Entry.objects.filter(authors__name=F('blog__name'))

दिनांक और दिनांक / समय फ़ील्ड के लिए, आप एक timedelta ऑब्जेक्ट जोड़ या घटा सकते हैं। निम्नलिखित सभी प्रविष्टियाँ लौटाएंगे, जो प्रकाशित होने के बाद 3 दिनों से अधिक समय से संशोधित थीं:

>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))

F() ऑब्जेक्ट .bitand() ऑपरेशंस को .bitand() , .bitor() , .bitrightshift() , और .bitleftshift() । उदाहरण के लिए:

>>> F('somefield').bitand(16)

pk लुकअप शॉर्टकट

सुविधा के लिए, Django एक pk लुकअप शॉर्टकट प्रदान करता है, जो "प्राथमिक कुंजी" के लिए खड़ा है।

उदाहरण Blog मॉडल में, प्राथमिक कुंजी id फ़ील्ड है, इसलिए ये तीन कथन समान हैं:

>>> Blog.objects.get(id__exact=14) # Explicit form
>>> Blog.objects.get(id=14) # __exact is implied
>>> Blog.objects.get(pk=14) # pk implies id__exact

__exact का उपयोग __exact क्वेरीज़ तक सीमित नहीं है - किसी भी क्वेरी शब्द को मॉडल की प्राथमिक कुंजी पर क्वेरी करने के लिए pk के साथ जोड़ा जा सकता है:

# Get blogs entries with id 1, 4 and 7
>>> Blog.objects.filter(pk__in=[1,4,7])

# Get all blog entries with id > 14
>>> Blog.objects.filter(pk__gt=14)

pk लुकअप भी pk भर में काम करता है। उदाहरण के लिए, ये तीनों कथन समतुल्य हैं:

>>> Entry.objects.filter(blog__id__exact=3) # Explicit form
>>> Entry.objects.filter(blog__id=3)        # __exact is implied
>>> Entry.objects.filter(blog__pk=3)        # __pk implies __id__exact

LIKE कथनों में प्रतिशत संकेत और अंडरस्कोर LIKE

फ़ील्ड iexact SQL कथन ( iexact , contains , icontains , startswith , istartswith , endswith और iendswith ) के istartswith , स्वचालित रूप से LIKE कथनों में उपयोग होने वाले दो विशेष वर्ण - प्रतिशत चिह्न और अंडरस्कोर से बच जाएगा। (एक LIKE स्टेटमेंट में, प्रतिशत चिन्ह एक मल्टीपल-कैरेक्टर वाइल्डकार्ड को दर्शाता है और अंडरस्कोर सिंगल-कैरेक्टर कार्डकार्ड को दर्शाता है।)

इसका मतलब है कि चीजों को सहज रूप से काम करना चाहिए, इसलिए अमूर्त रिसाव नहीं करता है। उदाहरण के लिए, उन सभी प्रविष्टियों को पुनः प्राप्त करने के लिए जिनमें एक प्रतिशत चिह्न है, बस किसी अन्य वर्ण के रूप में प्रतिशत चिह्न का उपयोग करें:

>>> Entry.objects.filter(headline__contains='%')

Django आपके लिए उद्धरण का ख्याल रखता है; परिणामस्वरूप SQL कुछ इस तरह दिखेगा:

SELECT ... WHERE headline LIKE '%\%%';

वही अंडरस्कोर करता है। दोनों प्रतिशत संकेत और अंडरस्कोर पारदर्शी रूप से आपके लिए हैं।

कैशिंग और QuerySet एस

प्रत्येक QuerySet में डेटाबेस एक्सेस को कम करने के लिए कैश होता है। यह समझना कि यह कैसे काम करता है, आपको सबसे कुशल कोड लिखने की अनुमति देगा।

एक नए बनाए गए QuerySet , कैश खाली है। पहली बार किसी QuerySet का मूल्यांकन किया जाता है - और, इसलिए, एक डेटाबेस क्वेरी होती है - Django क्वेरी परिणाम को क्वेरी के कैश में सहेजता है और परिणामों को स्पष्ट रूप से अनुरोध किया गया है (उदाहरण के लिए, अगले तत्व, अगर QuerySet को पुनरावृत्त किया जा रहा है) QuerySet है ऊपर)। QuerySet बाद के मूल्यांकन कैश्ड परिणामों का पुन: उपयोग करते हैं।

इस कैशिंग व्यवहार को ध्यान में रखें, क्योंकि यदि आप अपने QuerySet सही उपयोग नहीं करते हैं तो यह आपको काट सकता है। उदाहरण के लिए, निम्नलिखित दो QuerySet , उनका मूल्यांकन करेंगे, और उन्हें फेंक देंगे:

>>> print([e.headline for e in Entry.objects.all()])
>>> print([e.pub_date for e in Entry.objects.all()])

इसका मतलब है कि समान डेटाबेस क्वेरी को दो बार निष्पादित किया जाएगा, प्रभावी रूप से आपके डेटाबेस लोड को दोगुना कर देगा। इसके अलावा, संभावना है कि दो सूचियों में एक ही डेटाबेस रिकॉर्ड शामिल नहीं हो सकता है, क्योंकि दो अनुरोधों के बीच विभाजन दूसरे में एक Entry जोड़ी या हटा दी गई हो सकती है।

इस समस्या से बचने के लिए, बस QuerySet सेव करें और उसका पुनः उपयोग करें:

>>> queryset = Entry.objects.all()
>>> print([p.headline for p in queryset]) # Evaluate the query set.
>>> print([p.pub_date for p in queryset]) # Re-use the cache from the evaluation.

जब QuerySet s कैश नहीं हैं

क्वेरीज़ हमेशा उनके परिणामों को कैश नहीं करते हैं। क्वेरीसेट के केवल एक हिस्से का मूल्यांकन करते समय, कैश की जाँच की जाती है, लेकिन यदि यह पॉपुलेटेड नहीं है, तो बाद में क्वेरी द्वारा लौटाए गए आइटम कैश नहीं किए जाते हैं। विशेष रूप से, इसका मतलब है कि एक सरणी स्लाइस या एक इंडेक्स का उपयोग करके क्वेरीसेट को सीमित करना कैश को पॉप्युलेट नहीं करेगा।

उदाहरण के लिए, बार-बार क्वेरी ऑब्जेक्ट में एक निश्चित इंडेक्स प्राप्त करने से डेटाबेस हर बार क्वेरी करेगा:

>>> queryset = Entry.objects.all()
>>> print(queryset[5]) # Queries the database
>>> print(queryset[5]) # Queries the database again

हालाँकि, यदि पूरी क्वेरी का मूल्यांकन पहले ही किया जा चुका है, तो इसके बजाय कैश की जाँच की जाएगी:

>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset] # Queries the database
>>> print(queryset[5]) # Uses cache
>>> print(queryset[5]) # Uses cache

यहां अन्य कार्यों के कुछ उदाहरण दिए गए हैं, जिनके परिणामस्वरूप संपूर्ण क्वेरीसेट का मूल्यांकन किया जाएगा और इसलिए कैश को आबाद करें:

>>> [entry for entry in queryset]
>>> bool(queryset)
>>> entry in queryset
>>> list(queryset)

ध्यान दें

बस क्वेरी को प्रिंट करने से कैश पॉप्युलेट नहीं होगा। ऐसा इसलिए है क्योंकि __repr__() कॉल केवल संपूर्ण __repr__() एक टुकड़ा देता है।

Q वस्तुओं के साथ जटिल लुकअप

कीवर्ड तर्क क्वेरी - filter() , आदि - एक साथ "और" एड हैं। यदि आपको अधिक जटिल प्रश्नों को निष्पादित करने की आवश्यकता है (उदाहरण के लिए, OR कथन वाले प्रश्न), तो आप Q objects उपयोग कर सकते हैं।

एक Q object ( django.db.models.Q ) एक कीवर्ड तर्क का एक संग्रह encapsulate करने के लिए प्रयोग किया जाता है। ये कीवर्ड तर्क उपरोक्त "फ़ील्ड लुकअप" के रूप में निर्दिष्ट किए गए हैं।

उदाहरण के लिए, यह Q ऑब्जेक्ट एकल LIKE क्वेरी को अलग करता है:

from django.db.models import Q
Q(question__startswith='What')

Q वस्तुओं का उपयोग करके जोड़ा जा सकता है & | ऑपरेटरों। जब एक ऑपरेटर का उपयोग दो Q ऑब्जेक्ट पर किया जाता है, तो यह एक नई Q ऑब्जेक्ट देता है।

उदाहरण के लिए, यह कथन एक एकल Q ऑब्जेक्ट देता है जो दो "question__startswith" प्रश्नों के "OR" का प्रतिनिधित्व करता है:

Q(question__startswith='Who') | Q(question__startswith='What')

यह निम्न SQL WHERE क्लॉज के बराबर है:

WHERE question LIKE 'Who%' OR question LIKE 'What%'

आप Q वस्तुओं को & | साथ जोड़कर मनमानी जटिलता के बयान लिख सकते हैं संचालक और अभिभावक समूह का उपयोग करते हैं। इसके अलावा, Q ऑब्जेक्ट्स को ~ ऑपरेटर का उपयोग करके उपेक्षित किया जा सकता है, जो संयुक्त लुकअप के लिए अनुमति देता है जो एक सामान्य क्वेरी और एक नकारात्मक (दोनों) को जोड़ती है:

Q(question__startswith='Who') | ~Q(pub_date__year=2005)

प्रत्येक लुकअप फ़ंक्शन जो कीवर्ड-तर्क लेता है (उदाहरण के लिए filter() , exclude() , get() ) को भी एक या अधिक Q ऑब्जेक्ट्स को पोजिशनल (नामांकित नहीं) तर्कों के रूप में पास किया जा सकता है। यदि आप लुकअप फ़ंक्शन के लिए एकाधिक Q ऑब्जेक्ट तर्क प्रदान करते हैं, तो तर्क "AND" एड एक साथ होंगे। उदाहरण के लिए:

Poll.objects.get(
    Q(question__startswith='Who'),
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)

... मोटे तौर पर SQL में अनुवाद:

SELECT * from polls WHERE question LIKE 'Who%'
    AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

लुकअप फ़ंक्शन Q ऑब्जेक्ट और कीवर्ड तर्क के उपयोग को मिला सकता है। एक लुकअप फंक्शन को प्रदान की जाने वाली सभी दलीलें (वे कीवर्ड दलील या Q ऑब्जेक्ट हैं) एक साथ "और" एड हैं। हालाँकि, यदि कोई Q ऑब्जेक्ट प्रदान किया गया है, तो उसे किसी भी कीवर्ड तर्क की परिभाषा से पहले होना चाहिए। उदाहरण के लिए:

Poll.objects.get(
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
    question__startswith='Who',
)

… पिछले उदाहरण के बराबर एक मान्य क्वेरी होगी; परंतु:

# INVALID QUERY
Poll.objects.get(
    question__startswith='Who',
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)

... मान्य नहीं होगा।

यह भी देखें

Django इकाई परीक्षणों में OR लुकअप उदाहरण Q कुछ संभावित उपयोग दिखाते हैं।

वस्तुओं की तुलना करना

दो मॉडल उदाहरणों की तुलना करने के लिए, बस मानक पायथन तुलना ऑपरेटर का उपयोग करें, डबल बराबर चिह्न: == । पर्दे के पीछे, जो दो मॉडलों के प्राथमिक प्रमुख मूल्यों की तुलना करता है।

उपरोक्त Entry का उपयोग करते हुए, निम्नलिखित दो कथन समतुल्य हैं:

>>> some_entry == other_entry
>>> some_entry.id == other_entry.id

यदि किसी मॉडल की प्राथमिक कुंजी को id नहीं कहा जाता है, तो कोई बात नहीं। तुलना हमेशा प्राथमिक कुंजी का उपयोग करेगी, जो भी इसे कहा जाता है। उदाहरण के लिए, यदि किसी मॉडल के प्राथमिक कुंजी क्षेत्र को name कहा जाता है, तो ये दो कथन समतुल्य हैं:

>>> some_obj == other_obj
>>> some_obj.name == other_obj.name

वस्तुओं को हटाना

डिलीट विधि, सुविधापूर्वक, delete() का नाम है। यह विधि तुरंत ऑब्जेक्ट को हटा देती है और हटाए गए ऑब्जेक्ट की संख्या और ऑब्जेक्ट प्रकार के विलोपन की संख्या के साथ एक शब्दकोश लौटाती है। उदाहरण:

>>> e.delete()
(1, {'weblog.Entry': 1})

आप बल्क में ऑब्जेक्ट्स को हटा भी सकते हैं। हर QuerySet में एक delete() विधि होती है, जो उस QuerySet सभी सदस्यों को हटा QuerySet

उदाहरण के लिए, यह 2005 के pub_date वर्ष के साथ सभी Entry ऑब्जेक्ट को हटा देता है:

>>> Entry.objects.filter(pub_date__year=2005).delete()
(5, {'webapp.Entry': 5})

ध्यान रखें कि यह, जब भी संभव हो, विशुद्ध रूप से SQL में निष्पादित किया जाना चाहिए, और इसलिए व्यक्तिगत ऑब्जेक्ट इंस्टेंसेस के delete() तरीके जरूरी प्रक्रिया के दौरान नहीं बुलाए जाएंगे। यदि आपने किसी मॉडल वर्ग पर एक कस्टम delete() विधि प्रदान की है और यह सुनिश्चित करना चाहते हैं कि इसे कहा जाता है, तो आपको उस मॉडल के उदाहरणों को "मैन्युअल रूप से" डिलीट करने की आवश्यकता होगी (जैसे, एक QuerySet पर पुनरावृत्ति QuerySet और कॉल delete() प्रत्येक ऑब्जेक्ट व्यक्तिगत रूप से delete() QuerySet के बल्क delete() पद्धति का उपयोग करने के बजाय।

जब Django किसी ऑब्जेक्ट को हटाता है, तो डिफ़ॉल्ट रूप से यह SQL कसौटी ON DELETE CASCADE के व्यवहार का अनुकरण करता है - दूसरे शब्दों में, ऑब्जेक्ट को इंगित करने वाले विदेशी ऑब्जेक्ट्स को हटाने वाली कोई भी वस्तु इसके साथ हटा दी जाएगी। उदाहरण के लिए:

b = Blog.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()

यह कैस्केड व्यवहार on_delete तर्क के माध्यम से on_delete लिए अनुकूलन योग्य है।

ध्यान दें कि delete() एकमात्र QuerySet पद्धति है जो किसी Manager ही उजागर नहीं होती है। यह गलती से आपको Entry.objects.delete() , और सभी प्रविष्टियों को हटाने का अनुरोध करने से रोकने के लिए एक सुरक्षा तंत्र है। यदि आप सभी ऑब्जेक्ट हटाना चाहते हैं, तो आपको स्पष्ट रूप से एक संपूर्ण क्वेरी सेट का अनुरोध करना होगा:

Entry.objects.all().delete()

मॉडल उदाहरणों की नकल करना

यद्यपि मॉडल उदाहरणों की प्रतिलिपि बनाने के लिए कोई अंतर्निहित पद्धति नहीं है, फिर भी सभी क्षेत्रों के मूल्यों की नकल के साथ आसानी से नए उदाहरण बनाना संभव है। सरलतम मामले में, आप केवल pk को None सेट None कर सकते। हमारे ब्लॉग उदाहरण का उपयोग करना:

blog = Blog(name='My blog', tagline='Blogging is easy')
blog.save() # blog.pk == 1

blog.pk = None
blog.save() # blog.pk == 2

यदि आप विरासत का उपयोग करते हैं तो चीजें अधिक जटिल हो जाती हैं। Blog एक उपवर्ग पर विचार करें:

class ThemeBlog(Blog):
    theme = models.CharField(max_length=200)

django_blog = ThemeBlog(name='Django', tagline='Django is easy', theme='python')
django_blog.save() # django_blog.pk == 3

वंशानुक्रम कैसे काम करता है, इसके कारण आपको pk और id दोनों को किसी पर सेट करना होगा:

django_blog.pk = None
django_blog.id = None
django_blog.save() # django_blog.pk == 4

यह प्रक्रिया उन संबंधों को कॉपी नहीं करती है जो मॉडल के डेटाबेस तालिका का हिस्सा नहीं हैं। उदाहरण के लिए, Entry में Author लिए कई ManyToManyField है। एक प्रविष्टि की नकल करने के बाद, आपको नई प्रविष्टि के लिए कई-से-कई संबंध सेट करने होंगे:

entry = Entry.objects.all()[0] # some previous entry
old_authors = entry.authors.all()
entry.pk = None
entry.save()
entry.authors.set(old_authors)

OneToOneField , आपको संबंधित ऑब्जेक्ट का डुप्लिकेट करना होगा और एक-से-एक अनन्य अवरोध का उल्लंघन करने से बचने के लिए इसे नए ऑब्जेक्ट के क्षेत्र में असाइन करना होगा। उदाहरण के लिए, मान लिया गया है कि entry पहले से ही ऊपर की तरह दोहराई गई है:

detail = EntryDetail.objects.all()[0]
detail.pk = None
detail.entry = entry
detail.save()

एक साथ कई ऑब्जेक्ट्स को अपडेट करना

कभी-कभी आप किसी क्षेत्र को सभी वस्तुओं के लिए एक विशेष मान में सेट करना चाहते हैं QuerySet । आप इसे update() विधि के साथ कर सकते हैं । उदाहरण के लिए:

# Update all the headlines with pub_date in 2007.
Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

आप ForeignKey इस पद्धति का उपयोग करके केवल गैर-संबंध फ़ील्ड और फ़ील्ड सेट कर सकते हैं । एक गैर-संबंध क्षेत्र को अपडेट करने के लिए, एक स्थिर के रूप में नया मान प्रदान करें। ForeignKey फ़ील्ड अपडेट करने के लिए , नया मान सेट करें नया मॉडल उदाहरण जिसे आप इंगित करना चाहते हैं। उदाहरण के लिए:

>>> b = Blog.objects.get(pk=1)

# Change every Entry so that it belongs to this Blog.
>>> Entry.objects.all().update(blog=b)

यह update() विधि तुरंत लागू होती है और क्वेरी द्वारा मिलान की गई पंक्तियों की संख्या लौटाती है (जो कुछ पंक्तियों की संख्या के बराबर नहीं हो सकती है यदि कुछ पंक्तियों में पहले से ही नया मान है)। QuerySet अपडेट किए जाने पर एकमात्र प्रतिबंध यह है कि यह केवल एक डेटाबेस तालिका तक पहुंच सकता है: मॉडल की मुख्य तालिका। आप संबंधित क्षेत्रों के आधार पर फ़िल्टर कर सकते हैं, लेकिन आप केवल मॉडल की मुख्य तालिका में कॉलम अपडेट कर सकते हैं। उदाहरण:

>>> b = Blog.objects.get(pk=1)

# Update all the headlines belonging to this Blog.
>>> Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same')

ध्यान रखें कि update() विधि सीधे SQL स्टेटमेंट में बदल जाती है। यह प्रत्यक्ष अपडेट के लिए एक बल्क ऑपरेशन है। यह save() आपके मॉडल पर कोई भी विधि नहीं चलाता है , या सिग्नल pre_save या post_save (जो कॉल करने का परिणाम हैं save() ) या auto_now क्षेत्र विकल्प का सम्मान करते हैं । यदि आप प्रत्येक आइटम को एक में सहेजना चाहते हैं QuerySet और सुनिश्चित करें कि save() विधि प्रत्येक उदाहरण पर कॉल की जाती है, तो आपको इसे संभालने के लिए किसी विशेष फ़ंक्शन की आवश्यकता नहीं है। बस उन पर लूप करें और कॉल करें save() :

for item in my_queryset:
    item.save()

अद्यतन करने के लिए कॉल F expressions मॉडल में किसी अन्य फ़ील्ड के मूल्य के आधार पर एक फ़ील्ड को अपडेट करने के लिए भी उपयोग कर सकते हैं । यह उनके वर्तमान मूल्य के आधार पर काउंटरों को बढ़ाने के लिए विशेष रूप से उपयोगी है। उदाहरण के लिए, ब्लॉग में हर प्रविष्टि के लिए पिंगबैक गणना बढ़ाना:

>>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)

हालाँकि, F() फ़िल्टर में मौजूद वस्तुओं के विपरीत और क्लॉज़ को छोड़कर, जब आप F() किसी अद्यतन में ऑब्जेक्ट का उपयोग करते हैं, तो आप उससे जुड़ नहीं सकते - आप केवल अपडेट किए जा रहे मॉडल के लिए स्थानीय क्षेत्रों को संदर्भित कर सकते हैं। यदि आप किसी F() वस्तु से जुड़ने का प्रयास करते हैं , FieldError तो उठाया जाएगा:

# This will raise a FieldError
>>> Entry.objects.update(headline=F('blog__name'))

इस पृष्ठ के शीर्ष पर मॉडल का उपयोग करना, उदाहरण के लिए, एक Entry वस्तु विशेषता तक पहुंचकर e अपनी संबंधित Blog वस्तु प्राप्त कर सकती है :। blog e.blog

(परदे के पीछे, इस कार्यक्षमता अजगर द्वारा कार्यान्वित किया जाता descriptors । यह वास्तव में आप के लिए कोई फर्क नहीं करना चाहिए, लेकिन हम इसे यहाँ का कहना है उत्सुक के लिए।)

Django रिश्ते के "अन्य" पक्ष के लिए एपीआई एक्सेसर्स भी बनाता है - संबंध को परिभाषित करने वाले मॉडल से संबंधित मॉडल से लिंक। उदाहरण के लिए, किसी Blog ऑब्जेक्ट की विशेषता के माध्यम b से सभी संबंधित Entry वस्तुओं की सूची तक पहुंच होती है :। entry_set b.entry_set.all()

इस अनुभाग के सभी उदाहरण नमूने का उपयोग करते हैं Blog , Author और Entry इस पृष्ठ के शीर्ष पर परिभाषित मॉडल।

एक से कई रिश्ते

आगे

यदि किसी मॉडल में एक है ForeignKey , तो उस मॉडल के उदाहरणों में मॉडल की एक साधारण विशेषता के माध्यम से संबंधित (विदेशी) ऑब्जेक्ट तक पहुंच होगी।

उदाहरण:

>>> e = Entry.objects.get(id=2)
>>> e.blog # Returns the related Blog object.

आप एक विदेशी-कुंजी विशेषता के माध्यम से प्राप्त और सेट कर सकते हैं। जैसा कि आप उम्मीद कर सकते हैं, जब तक आप कॉल नहीं करते तब तक विदेशी कुंजी में परिवर्तन डेटाबेस में सहेजे नहीं जाते हैं save() । उदाहरण:

>>> e = Entry.objects.get(id=2)
>>> e.blog = some_blog
>>> e.save()

यदि कोई ForeignKey फ़ील्ड null=True सेट की गई है (यानी, यह NULL मानों को अनुमति देता है), तो आप None संबंध निकालने के लिए असाइन कर सकते हैं । उदाहरण:

>>> e = Entry.objects.get(id=2)
>>> e.blog = None
>>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;"

एक-से-कई रिश्तों को अग्रेषित करने के बाद पहली बार संबंधित वस्तु तक पहुँचने पर कैश किया जाता है। एक ही वस्तु उदाहरण पर विदेशी कुंजी के लिए बाद में पहुँच को कैश किया जाता है। उदाहरण:

>>> e = Entry.objects.get(id=2)
>>> print(e.blog)  # Hits the database to retrieve the associated Blog.
>>> print(e.blog)  # Doesn't hit the database; uses cached version.

ध्यान दें कि विधि समय से पहले सभी एक-से-कई रिश्तों के कैश को पूर्ववर्ती कर देती है। select_related() QuerySet उदाहरण:

>>> e = Entry.objects.select_related().get(id=2)
>>> print(e.blog)  # Doesn't hit the database; uses cached version.
>>> print(e.blog)  # Doesn't hit the database; uses cached version.

यदि किसी मॉडल में एक है ForeignKey , तो विदेशी-कुंजी मॉडल के Manager उदाहरणों में पहले मॉडल के सभी उदाहरणों की पहुंच होगी । डिफ़ॉल्ट रूप से, यह Manager नाम दिया गया है FOO_set , जहां FOO स्रोत मॉडल का नाम है, निचला। यह Manager रिटर्न QuerySets , जिसे फ़िल्टर्ड और हेरफेर किया जा सकता है जैसा कि ऊपर "रिट्रेक्टिंग ऑब्जेक्ट्स" सेक्शन में बताया गया है।

उदाहरण:

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all() # Returns all Entry objects related to Blog.

# b.entry_set is a Manager that returns QuerySets.
>>> b.entry_set.filter(headline__contains='Lennon')
>>> b.entry_set.count()

आप परिभाषा में पैरामीटर FOO_set सेट करके नाम को ओवरराइड कर सकते हैं । उदाहरण के लिए, यदि मॉडल में परिवर्तन किया गया था , तो उपरोक्त उदाहरण कोड इस तरह दिखाई देगा: related_name ForeignKey Entry blog = ForeignKey(Blog, on_delete=models.CASCADE, related_name='entries')

>>> b = Blog.objects.get(id=1)
>>> b.entries.all() # Returns all Entry objects related to Blog.

# b.entries is a Manager that returns QuerySets.
>>> b.entries.filter(headline__contains='Lennon')
>>> b.entries.count()

कस्टम रिवर्स मैनेजर का उपयोग करना

डिफ़ॉल्ट रूप से RelatedManager रिवर्स संबंधों के लिए उपयोग किया जाता है उस मॉडल के लिए डिफ़ॉल्ट प्रबंधक का एक उपवर्ग है । यदि आप किसी दिए गए प्रश्न के लिए एक अलग प्रबंधक निर्दिष्ट करना चाहते हैं, तो आप निम्नलिखित सिंटैक्स का उपयोग कर सकते हैं:

from django.db import models

class Entry(models.Model):
    #...
    objects = models.Manager()  # Default Manager
    entries = EntryManager()    # Custom Manager

b = Blog.objects.get(id=1)
b.entry_set(manager='entries').all()

यदि EntryManager इसकी get_queryset() विधि में डिफ़ॉल्ट फ़िल्टरिंग की जाती है, तो वह फ़िल्टरिंग all() कॉल पर लागू होगी ।

बेशक, कस्टम रिवर्स प्रबंधक को निर्दिष्ट करना आपको इसके कस्टम तरीकों को कॉल करने में सक्षम बनाता है:

b.entry_set(manager='entries').is_published()
add(obj1, obj2, ...)
निर्दिष्ट ऑब्जेक्ट ऑब्जेक्ट को संबंधित ऑब्जेक्ट सेट पर जोड़ता है।
create(**kwargs)
एक नई वस्तु बनाता है, इसे बचाता है और संबंधित ऑब्जेक्ट सेट में डालता है। नई बनाई गई वस्तु लौटाता है।
remove(obj1, obj2, ...)
संबंधित ऑब्जेक्ट सेट से निर्दिष्ट मॉडल ऑब्जेक्ट निकालता है।
clear()
संबंधित ऑब्जेक्ट से सभी ऑब्जेक्ट को निकालता है।
set(objs)
संबंधित वस्तुओं के सेट को बदलें।

संबंधित सेट के सदस्यों को असाइन करने के लिए, set() ऑब्जेक्ट इंस्टेंसेस के चलने योग्य के साथ विधि का उपयोग करें । उदाहरण के लिए, यदि उदाहरण हैं e1 और e2 हैं Entry :

b = Blog.objects.get(id=1)
b.entry_set.set([e1, e2])

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

इस खंड में वर्णित प्रत्येक "रिवर्स" ऑपरेशन का डेटाबेस पर तत्काल प्रभाव पड़ता है। प्रत्येक जोड़, निर्माण और विलोपन तुरंत और स्वचालित रूप से डेटाबेस में सहेजे जाते हैं।

कई-कई रिश्ते

कई-से-कई संबंधों के दोनों सिरों को दूसरे छोर तक स्वचालित API पहुंच मिलती है। एपीआई "पिछड़े" एक-से-कई संबंधों के समान है, ऊपर।

एक अंतर विशेषता नामकरण में है: वह मॉडल जो ManyToManyField उस फ़ील्ड के विशेषता नाम का उपयोग स्वयं को परिभाषित करता है, जबकि "रिवर्स" मॉडल मूल मॉडल के निचले स्तर वाले मॉडल नाम का उपयोग करता है, प्लस '_set' (ठीक एक से कई रिश्तों की तरह) ।

एक उदाहरण यह समझने में आसान बनाता है:

e = Entry.objects.get(id=3)
e.authors.all() # Returns all Author objects for this Entry.
e.authors.count()
e.authors.filter(name__contains='John')

a = Author.objects.get(id=5)
a.entry_set.all() # Returns all Entry objects for this Author.

जैसे ForeignKey , ManyToManyField निर्दिष्ट कर सकते हैं related_name । उपरोक्त उदाहरण में, यदि ManyToManyField में Entry निर्दिष्ट किया था related_name='entries' , तो प्रत्येक Author उदाहरण एक के लिए होता है entries के बजाय विशेषता entry_set

एक-से-कई रिश्तों से एक और अंतर यह है कि इसके अलावा में उदाहरणों, मॉडल करने के लिए है add() , set() और remove() कई-से-अनेक रिश्तों प्राथमिक कुंजी मान स्वीकार पर तरीकों। उदाहरण के लिए, यदि उदाहरण हैं e1 और e2 हैं Entry , तो ये set() कॉल पहचान से काम करते हैं:

a = Author.objects.get(id=5)
a.entry_set.set([e1, e2])
a.entry_set.set([e1.pk, e2.pk])

एक-से-एक रिश्ते

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

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

class EntryDetail(models.Model):
    entry = models.OneToOneField(Entry, on_delete=models.CASCADE)
    details = models.TextField()

ed = EntryDetail.objects.get(id=2)
ed.entry # Returns the related Entry object.

अंतर "रिवर्स" प्रश्नों में आता है। एक-से-एक संबंध में संबंधित मॉडल में भी किसी Manager ऑब्जेक्ट तक पहुंच होती है , लेकिन वह Manager वस्तुओं के संग्रह के बजाय किसी एकल ऑब्जेक्ट का प्रतिनिधित्व करता है:

e = Entry.objects.get(id=2)
e.entrydetail # returns the related EntryDetail object

यदि इस रिश्ते को कोई वस्तु नहीं दी गई है, तो Django एक DoesNotExist अपवाद को बढ़ाएगा ।

उदाहरणों को उल्टे रिश्ते को उसी तरह से सौंपा जा सकता है, जैसे आप आगे के रिश्ते को सौंपेंगे:

e.entrydetail = ed

पिछड़े रिश्ते कैसे संभव हैं?

अन्य ऑब्जेक्ट-रिलेशनल मैपर आपको दोनों पक्षों पर संबंधों को परिभाषित करने की आवश्यकता है। Django डेवलपर्स का मानना ​​है कि यह DRY (डोंट रिपीट योरसेल्फ) सिद्धांत का उल्लंघन है, इसलिए Django आपको केवल एक छोर पर संबंध को परिभाषित करने की आवश्यकता है।

लेकिन यह कैसे संभव है, यह देखते हुए कि एक मॉडल वर्ग को यह नहीं पता होता है कि अन्य मॉडल कक्षाएं लोड होने तक कौन से अन्य मॉडल वर्ग इससे संबंधित हैं?

जवाब में निहित है app registry । जब Django शुरू होता है, तो यह सूचीबद्ध प्रत्येक एप्लिकेशन को आयात करता है INSTALLED_APPS , और फिर models प्रत्येक एप्लिकेशन के अंदर मॉड्यूल। जब भी कोई नया मॉडल वर्ग बनाया जाता है, तो Django किसी भी संबंधित मॉडल में पिछड़े-संबंध जोड़ता है। यदि संबंधित मॉडल अभी तक आयात नहीं किए गए हैं, तो Django रिश्तों पर नज़र रखता है और उन्हें तब जोड़ता है जब संबंधित मॉडल अंततः आयात किए जाते हैं।

इस कारण से, यह विशेष रूप से महत्वपूर्ण है कि आपके द्वारा उपयोग किए जाने वाले सभी मॉडल में सूचीबद्ध अनुप्रयोगों में परिभाषित किया जाए INSTALLED_APPS । अन्यथा, पिछड़े संबंध ठीक से काम नहीं कर सकते हैं।

उदाहरण के लिए, यदि आपके पास एक ब्लॉग ऑब्जेक्ट b है id=5 , तो निम्नलिखित तीन प्रश्न समान होंगे:

Entry.objects.filter(blog=b) # Query using object instance
Entry.objects.filter(blog=b.id) # Query using id from instance
Entry.objects.filter(blog=5) # Query using id directly

कच्ची एसक्यूएल में वापस गिरना

यदि आप अपने आप को एक एसक्यूएल क्वेरी लिखने की जरूरत महसूस करते हैं जो कि Django के डेटाबेस-मैपर को संभालने के लिए बहुत जटिल है, तो आप हाथ से SQL लिखने पर वापस आ सकते हैं। कच्चे एसक्यूएल प्रश्नों को लिखने के लिए Django के पास कुछ विकल्प हैं; देखने के कच्चे एसक्यूएल प्रश्नों प्रदर्शन

अंत में, यह नोट करना महत्वपूर्ण है कि Django डेटाबेस परत केवल आपके डेटाबेस के लिए एक इंटरफ़ेस है। आप अपने डेटाबेस को अन्य टूल, प्रोग्रामिंग लैंग्वेज या डेटाबेस फ्रेमवर्क के माध्यम से एक्सेस कर सकते हैं; आपके डेटाबेस के बारे में Django- विशिष्ट कुछ भी नहीं है।

Original text