Django 2.1 - Model instance reference

मॉडल उदाहरण संदर्भ




django

मॉडल उदाहरण संदर्भ

यह दस्तावेज़ Model एपीआई के विवरण का वर्णन करता है। यह model और डेटाबेस क्वेरी गाइड में प्रस्तुत सामग्री पर बनाता है, इसलिए आप शायद इसे पढ़ने से पहले उन दस्तावेजों को पढ़ना और समझना चाहते हैं।

इस संदर्भ में हम डेटाबेस क्वेरी गाइड में प्रस्तुत उदाहरण वेबलॉग मॉडल का उपयोग करेंगे।

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

एक मॉडल का एक नया उदाहरण बनाने के लिए, बस इसे किसी भी अन्य पायथन वर्ग की तरह त्वरित करें:

class Model(**kwargs) [source]

कीवर्ड तर्क बस आपके मॉडल पर आपके द्वारा परिभाषित फ़ील्ड के नाम हैं। ध्यान दें कि किसी भी तरह से किसी मॉडल को इंस्टेंट करना आपके डेटाबेस को नहीं छूता है; उसके लिए, आपको save() आवश्यकता है save()

ध्यान दें

आपको __init__ विधि को ओवरराइड करके मॉडल को अनुकूलित करने के लिए लुभाया जा सकता है। यदि आप ऐसा करते हैं, तो, ध्यान रखें कि कॉलिंग सिग्नेचर को न बदलें क्योंकि किसी भी परिवर्तन से मॉडल की आवृत्ति को बचाया जा सकता है। __init__ ओवरराइड करने के बजाय, इन तरीकों में से एक का उपयोग करने का प्रयास करें:

  1. मॉडल वर्ग पर एक क्लासमेथोड जोड़ें:

    from django.db import models
    
    class Book(models.Model):
        title = models.CharField(max_length=100)
    
        @classmethod
        def create(cls, title):
            book = cls(title=title)
            # do something with the book
            return book
    
    book = Book.create("Pride and Prejudice")
    
  2. कस्टम प्रबंधक पर एक विधि जोड़ें (आमतौर पर पसंदीदा):

    class BookManager(models.Manager):
        def create_book(self, title):
            book = self.create(title=title)
            # do something with the book
            return book
    
    class Book(models.Model):
        title = models.CharField(max_length=100)
    
        objects = BookManager()
    
    book = Book.objects.create_book("Pride and Prejudice")
    

अनुरूपण मॉडल लोड हो रहा है

classmethod Model.from_db(db, field_names, values) [source]

डेटाबेस से लोड होने पर मॉडल आवृत्ति निर्माण को अनुकूलित करने के लिए from_db() विधि का उपयोग किया जा सकता है।

db तर्क में डेटाबेस के लिए डेटाबेस उपनाम शामिल होता है, जिससे मॉडल लोड किया जाता है, field_names में सभी लोड किए गए फ़ील्ड के नाम होते हैं, और values में field_names में प्रत्येक फ़ील्ड के लिए लोड किए गए मान शामिल होते हैं। field_names values के समान क्रम में values । यदि सभी मॉडल के क्षेत्र मौजूद हैं, तो values को आदेश में रहने की गारंटी दी जाती है __init__() उन्हें उम्मीद है। अर्थात्, उदाहरण cls(*values) द्वारा बनाया जा सकता है। यदि किसी भी क्षेत्र को स्थगित किया जाता है, तो वे field_names में दिखाई नहीं देंगे। उस स्थिति में, प्रत्येक लापता फ़ील्ड के लिए django.db.models.DEFERRED का मान असाइन करें।

नए मॉडल को बनाने के अलावा, from_db() विधि को नए उदाहरण के _state विशेषता में adding और db झंडे सेट करना होगा।

नीचे एक उदाहरण दिखाया गया है कि डेटाबेस से लोड किए गए फ़ील्ड के प्रारंभिक मान कैसे रिकॉर्ड करें:

from django.db.models import DEFERRED

@classmethod
def from_db(cls, db, field_names, values):
    # Default implementation of from_db() (subject to change and could
    # be replaced with super()).
    if len(values) != len(cls._meta.concrete_fields):
        values = list(values)
        values.reverse()
        values = [
            values.pop() if f.attname in field_names else DEFERRED
            for f in cls._meta.concrete_fields
        ]
    instance = cls(*values)
    instance._state.adding = False
    instance._state.db = db
    # customization to store the original field values on the instance
    instance._loaded_values = dict(zip(field_names, values))
    return instance

def save(self, *args, **kwargs):
    # Check how the current values differ from ._loaded_values. For example,
    # prevent changing the creator_id of the model. (This example doesn't
    # support cases where 'creator_id' is deferred).
    if not self._state.adding and (
            self.creator_id != self._loaded_values['creator_id']):
        raise ValueError("Updating the value of creator isn't allowed")
    super().save(*args, **kwargs)

ऊपर दिए गए उदाहरण से पता चलता है कि कैसे किया जाता है यह स्पष्ट करने के लिए एक पूर्ण from_db() कार्यान्वयन। इस मामले में निश्चित रूप से from_db() पद्धति में super() कॉल का उपयोग करना संभव होगा।

डेटाबेस से वस्तुओं को ताज़ा करना

यदि आप किसी मॉडल उदाहरण से किसी फ़ील्ड को हटाते हैं, तो इसे फिर से एक्सेस करना डेटाबेस से मूल्य को पुनः लोड करता है:

>>> obj = MyModel.objects.first()
>>> del obj.field
>>> obj.field  # Loads the field from the database
Model.refresh_from_db(using=None, fields=None) [source]

यदि आपको डेटाबेस से किसी मॉडल के मूल्यों को फिर से लोड करने की आवश्यकता है, तो आप refresh_from_db() विधि का उपयोग कर सकते हैं। जब इस पद्धति को तर्कों के बिना बुलाया जाता है, तो निम्न कार्य किए जाते हैं:

  1. मॉडल के सभी गैर-आस्थगित क्षेत्र डेटाबेस में वर्तमान में मौजूद मानों से अपडेट किए जाते हैं।
  2. कोई भी कैश्ड संबंध पुनः लोड किए गए उदाहरण से साफ़ हो जाते हैं।

मॉडल के केवल फ़ील्ड डेटाबेस से पुनः लोड किए गए हैं। अन्य डेटाबेस-निर्भर मान जैसे एनोटेशन पुनः लोड नहीं किए जाते हैं। कोई भी @cached_property विशेषताएँ साफ़ नहीं की गई हैं।

यदि डेटाबेस डेटाबेस से लोड नहीं किया गया था, तो डेटाबेस से लोड हो रहा है या डिफ़ॉल्ट डेटाबेस से लोड हो रहा है। पुन: लोड करने के लिए उपयोग किए जाने वाले डेटाबेस को बाध्य करने के लिए उपयोग करने वाले तर्क का using किया जा सकता है।

fields तर्क का उपयोग करके फ़ील्ड के सेट को लोड करने के लिए बाध्य करना संभव है।

उदाहरण के लिए, यह जांचने के लिए कि update() कॉल के परिणामस्वरूप अपेक्षित अपडेट हुआ, आप इसके समान परीक्षण लिख सकते हैं:

def test_update_result(self):
    obj = MyModel.objects.create(val=1)
    MyModel.objects.filter(pk=obj.pk).update(val=F('val') + 1)
    # At this point obj.val is still 1, but the value in the database
    # was updated to 2. The object's updated value needs to be reloaded
    # from the database.
    obj.refresh_from_db()
    self.assertEqual(obj.val, 2)

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

class ExampleModel(models.Model):
    def refresh_from_db(self, using=None, fields=None, **kwargs):
        # fields contains the name of the deferred field to be
        # loaded.
        if fields is not None:
            fields = set(fields)
            deferred_fields = self.get_deferred_fields()
            # If any deferred field is going to be loaded
            if fields.intersection(deferred_fields):
                # then load all of them
                fields = fields.union(deferred_fields)
        super().refresh_from_db(using, fields, **kwargs)
Model.get_deferred_fields() [source]

एक सहायक विधि जो एक सेट लौटाती है जिसमें उन सभी क्षेत्रों के विशेषता नाम होते हैं जो वर्तमान में इस मॉडल के लिए आस्थगित हैं।

वस्तुओं को वैध करना

एक मॉडल को मान्य करने में तीन चरण शामिल हैं:

  1. मॉडल फ़ील्ड सत्यापित करें - Model.clean_fields()
  2. मॉडल को संपूर्ण के रूप में मान्य करें - Model.clean()
  3. फ़ील्ड विशिष्टता को मान्य करें - Model.validate_unique()

जब आप किसी मॉडल का full_clean() विधि कहते हैं, तो सभी तीन चरण किए जाते हैं।

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

Model.full_clean(exclude=None, validate_unique=True) [source]

यह विधि उस क्रम में Model.clean_fields() , Model.clean() , और Model.validate_unique() (यदि validate_unique True ) को कॉल Model.clean_fields() , और उस ValidationError उठाती है जिसमें तीन चरणों से त्रुटियों वाले एक message_dict विशेषता है।

वैकल्पिक exclude तर्क का उपयोग फ़ील्ड नामों की एक सूची प्रदान करने के लिए किया जा सकता है जिन्हें सत्यापन और सफाई से बाहर रखा जा सकता है। ModelForm इस तर्क का उपयोग उन फ़ील्ड्स को बाहर करने के लिए करता है जो आपके फ़ॉर्म पर मान्य नहीं हैं क्योंकि उपयोगकर्ता द्वारा उठाए गए किसी भी त्रुटि को ठीक नहीं किया जा सकता है।

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

from django.core.exceptions import ValidationError
try:
    article.full_clean()
except ValidationError as e:
    # Do something based on the errors contained in e.message_dict.
    # Display them to a user, or handle them programmatically.
    pass

प्रत्येक व्यक्तिगत फ़ील्ड को साफ़ करने के लिए पहला चरण full_clean() करता है।

Model.clean_fields(exclude=None) [source]

यह विधि आपके मॉडल के सभी क्षेत्रों को मान्य करेगी। वैकल्पिक exclude तर्क आपको सत्यापन से बाहर करने के लिए फ़ील्ड नामों की एक सूची प्रदान करता है। यदि कोई क्षेत्र सत्यापन विफल हो जाता है तो यह वैधता बढ़ा देगा।

दूसरा चरण full_clean() करता है, जिसे Model.clean() । इस पद्धति को आपके मॉडल पर कस्टम सत्यापन करने के लिए ओवरराइड किया जाना चाहिए।

Model.clean() [source]

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

import datetime
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext_lazy as _

class Article(models.Model):
    ...
    def clean(self):
        # Don't allow draft entries to have a pub_date.
        if self.status == 'draft' and self.pub_date is not None:
            raise ValidationError(_('Draft entries may not have a publication date.'))
        # Set the pub_date for published items if it hasn't been set already.
        if self.status == 'published' and self.pub_date is None:
            self.pub_date = datetime.date.today()

ध्यान दें, हालांकि, जैसे कि full_clean() , मॉडल का clean() पद्धति को लागू नहीं किया जाता है जब आप अपने मॉडल की save() विधि कहते हैं।

उपरोक्त उदाहरण में, Model.clean() द्वारा उठाया गया ValidationError अपवाद एक स्ट्रिंग के साथ Model.clean() था, इसलिए इसे एक विशेष त्रुटि शब्दकोश कुंजी, NON_FIELD_ERRORS में संग्रहीत किया जाएगा। इस कुंजी का उपयोग उन त्रुटियों के लिए किया जाता है जो किसी विशिष्ट क्षेत्र के बजाय पूरे मॉडल से जुड़ी होती हैं:

from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
try:
    article.full_clean()
except ValidationError as e:
    non_field_errors = e.message_dict[NON_FIELD_ERRORS]

किसी विशिष्ट फ़ील्ड के अपवादों को असाइन करने के लिए, ValidationError को एक शब्दकोष के साथ त्वरित करें, जहाँ कुंजियाँ फ़ील्ड नाम हैं। हम pub_date फ़ील्ड में त्रुटि असाइन करने के लिए पिछले उदाहरण को अपडेट कर सकते हैं:

class Article(models.Model):
    ...
    def clean(self):
        # Don't allow draft entries to have a pub_date.
        if self.status == 'draft' and self.pub_date is not None:
            raise ValidationError({'pub_date': _('Draft entries may not have a publication date.')})
        ...

यदि आप Model.clean() दौरान कई क्षेत्रों में त्रुटियों का पता लगाते हैं, तो आप त्रुटियों के लिए एक शब्दकोश मानचित्रण फ़ील्ड नाम भी पास कर सकते हैं:

raise ValidationError({
    'title': ValidationError(_('Missing title.'), code='required'),
    'pub_date': ValidationError(_('Invalid date.'), code='invalid'),
})

अंत में, full_clean() आपके मॉडल पर किसी भी अद्वितीय बाधाओं की जाँच करेगा।

अगर फ़ील्ड उन ModelForm में दिखाई नहीं देता है तो फ़ील्ड-विशिष्ट सत्यापन त्रुटियों को कैसे बढ़ाएं

आप मॉडल के रूप में प्रकट नहीं होने वाले फ़ील्ड के लिए Model.clean() में सत्यापन त्रुटियों को नहीं बढ़ा सकते हैं (एक रूप Meta.fields या Meta.exclude का उपयोग करके अपने फ़ील्ड को सीमित कर सकते हैं)। ऐसा करना एक ValueError को बढ़ाएगा क्योंकि सत्यापन त्रुटि को शामिल किए गए फ़ील्ड से संबद्ध नहीं किया जा सकेगा।

इस दुविधा के आसपास काम करने के बजाय, Model.clean_fields() को ओवरराइड करें क्योंकि यह उन क्षेत्रों की सूची प्राप्त करता है जिन्हें सत्यापन से बाहर रखा गया है। उदाहरण के लिए:

class Article(models.Model):
    ...
    def clean_fields(self, exclude=None):
        super().clean_fields(exclude=exclude)
        if self.status == 'draft' and self.pub_date is not None:
            if exclude and 'status' in exclude:
                raise ValidationError(
                    _('Draft entries may not have a publication date.')
                )
            else:
                raise ValidationError({
                    'status': _(
                        'Set status to draft if there is not a '
                        'publication date.'
                     ),
                })
Model.validate_unique(exclude=None) [source]

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

ध्यान दें कि यदि आप validate_unique() को एक exclude तर्क प्रदान करते हैं, तो आपके द्वारा दिए गए क्षेत्रों में से एक को शामिल करने वाले किसी भी unique_together अवरोध को जांचा नहीं जाएगा।

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

किसी ऑब्जेक्ट को डेटाबेस में वापस लाने के लिए, कॉल save() :

Model.save(force_insert=False, force_update=False, using=DEFAULT_DB_ALIAS, update_fields=None) [source]

यदि आप अनुकूलित बचत व्यवहार चाहते हैं, तो आप इस save() विधि को ओवरराइड कर सकते हैं। अधिक विवरण के लिए पूर्वनिर्धारित मॉडल विधियों को ओवरराइड करना देखें।

मॉडल सहेजें प्रक्रिया में कुछ सूक्ष्मताएं भी हैं; नीचे अनुभाग देखें।

ऑटो-इंक्रीमेंटिंग प्राथमिक कुंजी

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

>>> b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b2.id     # Returns None, because b doesn't have an ID yet.
>>> b2.save()
>>> b2.id     # Returns the ID of your new object.

आपके द्वारा save() कॉल करने से पहले किसी आईडी का मूल्य क्या होगा, यह बताने का कोई तरीका नहीं है, क्योंकि उस मूल्य की गणना आपके डेटाबेस द्वारा की जाती है, न कि Django के द्वारा।

सुविधा के लिए, प्रत्येक मॉडल में एक AutoField id जिसे डिफ़ॉल्ट रूप से तब तक निर्दिष्ट किया जाता है जब तक कि आप स्पष्ट रूप से अपने मॉडल में एक फ़ील्ड पर primary_key=True निर्दिष्ट primary_key=True करें। अधिक जानकारी के लिए AutoField लिए प्रलेखन देखें।

pk संपत्ति

Model.pk

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

स्पष्ट रूप से ऑटो-प्राथमिक-प्रमुख मान निर्दिष्ट करना

यदि किसी मॉडल में एक AutoField लेकिन आप सहेजते समय किसी नई ऑब्जेक्ट की ID को स्पष्ट रूप से परिभाषित करना चाहते हैं, तो बस इसे सहेजने से पहले स्पष्ट रूप से परिभाषित करें, बजाय ID के ऑटो असाइनमेंट पर निर्भर होने के:

>>> b3 = Blog(id=3, name='Cheddar Talk', tagline='Thoughts on cheese.')
>>> b3.id     # Returns 3.
>>> b3.save()
>>> b3.id     # Returns 3.

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

उपरोक्त 'Cheddar Talk' ब्लॉग उदाहरण को देखते हुए, यह उदाहरण डेटाबेस में पिछले रिकॉर्ड को अधिरोहित करेगा:

b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
b4.save()  # Overrides the previous blog with ID=3!

यह कैसे होता है, इसके लिए नीचे देखें कि कैसे Django , नीचे बनाम इनसेट को जानता है।

स्पष्ट रूप से ऑटो-प्राथमिक-कुंजी मूल्यों को निर्दिष्ट करना थोक-बचत वस्तुओं के लिए ज्यादातर उपयोगी है, जब आप आश्वस्त होते हैं कि आपके पास प्राथमिक-कुंजी टकराव नहीं होगा।

यदि आप PostgreSQL का उपयोग कर रहे हैं, तो प्राथमिक कुंजी से जुड़े अनुक्रम को अद्यतन करने की आवश्यकता हो सकती है; ऑटो-इन्क्रिमिंग प्राथमिक कुंजी के मैन्युअल-निर्दिष्ट मान देखें।

जब आप बचाते हैं तो क्या होता है?

जब आप किसी ऑब्जेक्ट को सहेजते हैं, तो Django निम्न चरणों का पालन करता है:

  1. प्री-सेव सिग्नल से बाहर निकलें। pre_save सिग्नल भेजा जाता है, जिससे किसी भी फ़ंक्शन को उस सिग्नल को सुनने के लिए कुछ करने की अनुमति मिलती है।
  2. डेटा को प्रीप्रोसेस करें। प्रत्येक फ़ील्ड के pre_save() विधि को किसी भी स्वचालित डेटा संशोधन को करने के लिए कहा जाता है जिसकी आवश्यकता होती है। उदाहरण के लिए, दिनांक / समय फ़ील्ड auto_now_add और auto_now को लागू करने के लिए pre_save() को ओवरराइड auto_now
  3. डेटाबेस के लिए डेटा तैयार करें। प्रत्येक फ़ील्ड का get_db_prep_save() विधि डेटा प्रकार में अपना वर्तमान मूल्य प्रदान करने के लिए कहा जाता है जिसे डेटाबेस में लिखा जा सकता है।

    अधिकांश क्षेत्रों में डेटा तैयार करने की आवश्यकता नहीं होती है। सरल डेटा प्रकार, जैसे पूर्णांक और तार, पायथन ऑब्जेक्ट के रूप में 'लिखने के लिए तैयार' हैं। हालांकि, अधिक जटिल डेटा प्रकारों में अक्सर कुछ संशोधन की आवश्यकता होती है।

    उदाहरण के लिए, DateField फ़ील्ड डेटा संग्रहीत करने के लिए पायथन DateField ऑब्जेक्ट का उपयोग करती हैं। डेटाबेस datetime ऑब्जेक्ट्स को संग्रहीत नहीं करता है, इसलिए फ़ील्ड मान को डेटाबेस में प्रविष्टि के लिए आईएसओ-अनुरूप तारीख स्ट्रिंग में परिवर्तित किया जाना चाहिए।

  4. डेटाबेस में डेटा डालें। प्रीप्रोसेस, तैयार डेटा डेटाबेस में प्रविष्टि के लिए एक एसक्यूएल स्टेटमेंट में बना है।
  5. एक बाद बचाने के संकेत का उत्सर्जन करें। post_save सिग्नल भेजा जाता है, जिससे किसी भी कार्य को सुनने के लिए उस सिग्नल को सुनने की अनुमति मिलती है।

कैसे Django जानता है बनाम INSERT

आपने देखा होगा कि Django डेटाबेस ऑब्जेक्ट्स बनाने और बदलने के लिए समान save() विधि का उपयोग करते हैं। Django को INSERT या UPDATE SQL कथनों का उपयोग करने की आवश्यकता है। विशेष रूप से, जब आप save() कॉल करते हैं save() , Django इस एल्गोरिथ्म का अनुसरण करता है:

  • यदि ऑब्जेक्ट की प्राथमिक कुंजी विशेषता एक मान पर सेट होती है जो True (यानी, None या खाली स्ट्रिंग के अलावा अन्य) का मूल्यांकन करता है, तो Django एक UPDATE निष्पादित करता है।
  • यदि ऑब्जेक्ट की प्राथमिक कुंजी विशेषता सेट नहीं है या यदि UPDATE ने कुछ भी अपडेट नहीं किया है, तो Django एक INSERT निष्पादित करता है।

यहां एक गोटा यह है कि आपको नई वस्तुओं को सहेजते समय एक प्राथमिक-कुंजी मूल्य स्पष्ट रूप से निर्दिष्ट नहीं करने के लिए सावधान रहना चाहिए, यदि आप गारंटी नहीं दे सकते कि प्राथमिक-कुंजी मूल्य अप्रयुक्त है। इस बारीकियों के बारे में अधिक जानने के लिए, ऊपर दिए गए ऑटो-प्राथमिक-प्रमुख मूल्यों को स्पष्ट रूप से निर्दिष्ट करें और नीचे एक INSERT या UPD मजबूर करें देखें।

Django 1.5 और इससे पहले, प्राथमिक कुंजी विशेषता सेट होने पर Django ने एक SELECT किया था। यदि SELECT एक पंक्ति मिली, तो Django ने एक UPDATE , अन्यथा यह एक INSERT । पुराने एल्गोरिथ्म के परिणामस्वरूप UPDATE स्थिति में एक और क्वेरी होती है। कुछ दुर्लभ मामले हैं जहां डेटाबेस रिपोर्ट नहीं करता है कि एक पंक्ति को अद्यतन किया गया था भले ही डेटाबेस में ऑब्जेक्ट के प्राथमिक कुंजी मान के लिए एक पंक्ति हो। एक उदाहरण ON UPDATE ट्रिगर ON UPDATE PostgreSQL है जो NULL लौटाता NULL । ऐसे मामलों में यह सही करने के लिए select_on_save विकल्प सेट करके पुराने एल्गोरिथ्म पर वापस जाना संभव है।

एक INSERT या UPDATE को मजबूर करना

कुछ दुर्लभ परिस्थितियों में, SQL INSERT करने के लिए save() विधि को लागू करने और UPDATE करने के लिए वापस न आने के लिए सक्षम होना आवश्यक है। या इसके विपरीत: अद्यतन, यदि संभव हो, लेकिन एक नई पंक्ति न डालें। इन मामलों में आप force_insert=True या force_update=True save() विधि के force_update=True मापदंडों को पास कर सकते हैं। जाहिर है, दोनों मापदंडों को पारित करना एक त्रुटि है: आप एक ही समय में सम्मिलित और अपडेट दोनों नहीं कर सकते हैं!

यह बहुत दुर्लभ होना चाहिए कि आपको इन मापदंडों का उपयोग करने की आवश्यकता होगी। Django लगभग हमेशा सही काम करेगा और ओवरराइड करने की कोशिश करेगा जिससे त्रुटियों को ट्रैक करने में मुश्किल होगी। यह सुविधा केवल उन्नत उपयोग के लिए है।

update_fields का उपयोग update_fields update के समान अद्यतन को बाध्य करेगा।

मौजूदा फ़ील्ड्स के आधार पर विशेषताएँ अपडेट करना

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

>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold += 1
>>> product.save()

यदि डेटाबेस से प्राप्त पुरानी number_sold मान 10 था, तो 11 का मान डेटाबेस में वापस लिखा जाएगा।

प्रक्रिया को मजबूत बनाया जा सकता है, एक दौड़ की स्थिति से बचने के साथ-साथ मूल क्षेत्र मूल्य के सापेक्ष अद्यतन को व्यक्त करके थोड़ा तेज, बल्कि एक नए मूल्य के स्पष्ट असाइनमेंट के रूप में। Django इस तरह के सापेक्ष अद्यतन करने के लिए F expressions प्रदान करता है। F expressions का उपयोग करते हुए, पिछले उदाहरण को इस प्रकार व्यक्त किया गया है:

>>> from django.db.models import F
>>> product = Product.objects.get(name='Venezuelan Beaver Cheese')
>>> product.number_sold = F('number_sold') + 1
>>> product.save()

अधिक विवरणों के लिए, F expressions पर प्रलेखन और अद्यतन प्रश्नों में उनके उपयोग को देखें

निर्दिष्ट करना कि कौन से फ़ील्ड को सहेजना है

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

product.name = 'Name changed again'
product.save(update_fields=['name'])

update_fields तर्क किसी भी update_fields तार हो सकता है। खाली update_fields पुनरावृति सहेजना छोड़ देगा। सभी क्षेत्रों में कोई भी मान अपडेट नहीं करेगा।

update_fields को निर्दिष्ट करने से एक अद्यतन मजबूर हो जाएगा।

डिफर्ड मॉडल लोडिंग ( only() या defer() ) के माध्यम से लाए गए मॉडल को सहेजते समय केवल DB से लोड किए गए फ़ील्ड अपडेट हो जाएंगे। update_fields में इस मामले में एक स्वचालित update_fields है। यदि आप किसी भी आस्थगित फ़ील्ड मान को असाइन या बदलते हैं, तो फ़ील्ड को अपडेट किए गए फ़ील्ड में जोड़ दिया जाएगा।

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

Model.delete(using=DEFAULT_DB_ALIAS, keep_parents=False) [source]

ऑब्जेक्ट के लिए SQL DELETE करता है। यह केवल डेटाबेस में ऑब्जेक्ट को हटाता है; पायथन उदाहरण अभी भी मौजूद है और इसके क्षेत्रों में अभी भी डेटा होगा। यह विधि हटाए गए ऑब्जेक्ट की संख्या और ऑब्जेक्ट प्रकार प्रति विलोपन की संख्या के साथ एक शब्दकोश देता है।

अधिक विवरणों के लिए, जिसमें बल्क में वस्तुओं को हटाना शामिल है, वस्तुओं को हटाना देखें।

यदि आप अनुकूलित विलोपन व्यवहार चाहते हैं, तो आप delete() विधि को ओवरराइड कर सकते हैं। अधिक विवरण के लिए पूर्वनिर्धारित मॉडल विधियों को ओवरराइड करना देखें।

कभी - कभी मल्टी-टेबल इनहेरिटेंस के साथ आप केवल एक बच्चे के मॉडल के डेटा को हटाना चाह सकते हैं। keep_parents=True निर्दिष्ट करना keep_parents=True माता-पिता के मॉडल का डेटा रखेगा।

अचार बनाने की वस्तु

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

आप अचार को संस्करणों के बीच साझा नहीं कर सकते

मॉडल के अचार केवल Django के संस्करण के लिए मान्य हैं जो उन्हें उत्पन्न करने के लिए उपयोग किया गया था। यदि आप Django वर्जन N का उपयोग करके अचार बनाते हैं, तो इस बात की कोई गारंटी नहीं है कि अचार Django के संस्करण N + 1 के साथ पढ़ने योग्य होगा। अचार को दीर्घकालिक अभिलेखीय रणनीति के भाग के रूप में उपयोग नहीं किया जाना चाहिए।

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

अन्य मॉडल उदाहरण के तरीके

कुछ ऑब्जेक्ट विधियों के विशेष उद्देश्य हैं।

__str__()

Model.__str__() [source]

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

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

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

    def __str__(self):
        return '%s %s' % (self.first_name, self.last_name)

__eq__()

Model.__eq__() [source]

समानता पद्धति को ऐसे परिभाषित किया गया है कि एक ही प्राथमिक कुंजी मूल्य के साथ इंस्टेंसेस और समान ठोस वर्ग को समान माना जाता है, सिवाय इसके कि प्राथमिक कुंजी मान के साथ इंस्टेंसेस स्वयं के अलावा किसी भी चीज के बराबर None हैं। प्रॉक्सी मॉडल के लिए, ठोस वर्ग को मॉडल के पहले गैर-प्रॉक्सी माता-पिता के रूप में परिभाषित किया गया है; अन्य सभी मॉडलों के लिए यह बस मॉडल की कक्षा है।

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

from django.db import models

class MyModel(models.Model):
    id = models.AutoField(primary_key=True)

class MyProxyModel(MyModel):
    class Meta:
        proxy = True

class MultitableInherited(MyModel):
    pass

# Primary keys compared
MyModel(id=1) == MyModel(id=1)
MyModel(id=1) != MyModel(id=2)
# Primary keys are None
MyModel(id=None) != MyModel(id=None)
# Same instance
instance = MyModel(id=None)
instance == instance
# Proxy model
MyModel(id=1) == MyProxyModel(id=1)
# Multi-table inheritance
MyModel(id=1) != MultitableInherited(id=1)

__hash__()

Model.__hash__() [source]

__hash__() विधि उदाहरण के प्राथमिक मुख्य मान पर आधारित है। यह प्रभावी रूप से hash(obj.pk) । यदि उदाहरण में प्राथमिक कुंजी मान नहीं है, तो एक TypeError को उठाया जाएगा (अन्यथा __hash__() विधि सहेजे जाने से पहले और बाद में भिन्न मान लौटाएगा, लेकिन __hash__() में __hash__() मान को बदलना मना है) ।

get_absolute_url()

Model.get_absolute_url()

Django को किसी ऑब्जेक्ट के लिए कैनोनिकल URL की गणना कैसे करें, यह बताने के लिए get_absolute_url() विधि को परिभाषित करें। कॉल करने वालों के लिए, यह विधि एक स्ट्रिंग को लौटाने के लिए दिखाई देनी चाहिए जिसका उपयोग HTTP पर ऑब्जेक्ट को संदर्भित करने के लिए किया जा सकता है।

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

def get_absolute_url(self):
    return "/people/%i/" % self.id

हालांकि यह कोड सही और सरल है, लेकिन इस तरह का तरीका लिखने का यह सबसे पोर्टेबल तरीका नहीं हो सकता है। reverse() फ़ंक्शन आमतौर पर सबसे अच्छा तरीका है।

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

def get_absolute_url(self):
    from django.urls import reverse
    return reverse('people.views.details', args=[str(self.id)])

एक जगह Django get_absolute_url() का उपयोग व्यवस्थापक ऐप में करता है। यदि कोई ऑब्जेक्ट इस पद्धति को परिभाषित करता है, तो ऑब्जेक्ट-एडिटिंग पेज में एक "व्यू ऑन साइट" लिंक होगा जो आपको ऑब्जेक्ट के सार्वजनिक दृश्य पर सीधे कूद जाएगा, जैसा कि get_absolute_url() द्वारा दिया गया है।

इसी तरह, Django के अन्य बिट्स, जैसे सिंडिकेशन फ़ीड रूपरेखा , परिभाषित होने पर get_absolute_url() उपयोग करें। यदि यह आपके मॉडल के उदाहरणों के लिए प्रत्येक के लिए एक अद्वितीय URL है, तो आपको get_absolute_url() को परिभाषित करना चाहिए।

चेतावनी

लिंक या रीडायरेक्ट पॉइज़निंग की संभावनाओं को कम करने के लिए, आपको URL को अनलिमिटेड उपयोगकर्ता इनपुट से बनाने से बचना चाहिए:

def get_absolute_url(self):
    return '/%s/' % self.name

यदि self.name '/example.com' यह '//example.com/' देता है, जो बदले में एक मान्य स्कीमा सापेक्ष URL है, लेकिन अपेक्षित '/%2Fexample.com/'

अपनी वस्तुओं के URL को हार्ड-कोड करने के बजाय, टेम्पलेट में get_absolute_url() का उपयोग करना अच्छा है। उदाहरण के लिए, यह टेम्प्लेट कोड खराब है:

<!-- BAD template code. Avoid! -->
<a href="/people/{{ object.id }}/">{{ object.name }}</a>

यह टेम्प्लेट कोड बहुत बेहतर है:

<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>

यहाँ तर्क यह है कि यदि आप अपनी वस्तुओं की URL संरचना को बदलते हैं, यहाँ तक कि किसी साधारण चीज़ के लिए भी जैसे कि वर्तनी की त्रुटि को ठीक करना, तो आप हर उस स्थान को ट्रैक नहीं करना चाहते जिसे URL बनाया जा सकता है। एक बार इसे get_absolute_url() में निर्दिष्ट करें और अपने सभी अन्य कोड को उस एक स्थान पर कॉल करें।

ध्यान दें

यदि आप get_absolute_url() से get_absolute_url() हैं, तो केवल ASCII वर्ण (URI विनिर्देशन, RFC 2396 द्वारा आवश्यक) और आवश्यक होने पर URL-एन्कोडेड होना चाहिए।

get_absolute_url() को कॉल करने वाले कोड और टेम्प्लेट किसी भी आगे की प्रक्रिया के बिना सीधे परिणाम का उपयोग करने में सक्षम होना चाहिए। यदि आप ASCII रेंज के बाहर वाले वर्णों का उपयोग कर रहे हैं, तो आप इसकी सहायता के लिए django.utils.encoding.iri_to_uri() फ़ंक्शन का उपयोग करना django.utils.encoding.iri_to_uri() सकते हैं।

अतिरिक्त उदाहरण के तरीके

save() , delete() , एक मॉडल ऑब्जेक्ट में कुछ निम्न तरीके हो सकते हैं:

Model.get_FOO_display()

प्रत्येक फ़ील्ड के लिए जिसमें choices सेट होते हैं, ऑब्जेक्ट में एक get_FOO_display() विधि होगी, जहां FOO फ़ील्ड का नाम है। यह विधि फ़ील्ड का "मानव-पठनीय" मान लौटाती है।

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

from django.db import models

class Person(models.Model):
    SHIRT_SIZES = (
        ('S', 'Small'),
        ('M', 'Medium'),
        ('L', 'Large'),
    )
    name = models.CharField(max_length=60)
    shirt_size = models.CharField(max_length=2, choices=SHIRT_SIZES)
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'
Model.get_next_by_FOO(**kwargs)
Model.get_previous_by_FOO(**kwargs)

प्रत्येक DateField और DateTimeField जिसमें null=True नहीं है, ऑब्जेक्ट के पास get_next_by_FOO() और get_previous_by_FOO() विधियाँ get_previous_by_FOO() , जहाँ FOO फ़ील्ड का नाम है। यह अगली और पिछली वस्तु को दिनांक फ़ील्ड के संबंध में DoesNotExist है, जब उचित होता है एक DoesNotExist अपवाद को DoesNotExist है।

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

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

अन्य विशेषताएँ

DoesNotExist

exception Model.DoesNotExist

यह अपवाद ORM द्वारा युगल स्थानों में उठाया जाता है, उदाहरण के लिए QuerySet.get() द्वारा जब किसी ऑब्जेक्ट को दिए गए क्वेरी मापदंडों के लिए नहीं पाया जाता है।

Django ऑब्जेक्ट के वर्ग की पहचान करने के लिए प्रत्येक मॉडल वर्ग की एक विशेषता के रूप में एक DoesNotExist अपवाद प्रदान करता है जो कि नहीं पाया जा सकता है और आपको किसी विशेष मॉडल वर्ग को try/except पकड़ने की अनुमति देता है। अपवाद django.core.exceptions.ObjectDoesNotExist उपवर्ग है।