Django 2.1 - Serializing Django objects

Django ऑब्जेक्ट्स को सीरियल करना




django

Django ऑब्जेक्ट्स को सीरियल करना

Django के क्रमांकन ढांचे को अन्य स्वरूपों में Django मॉडल "अनुवाद" के लिए एक तंत्र प्रदान करता है। आमतौर पर ये अन्य प्रारूप टेक्स्ट-आधारित होंगे और इसका उपयोग एक तार पर Django डेटा भेजने के लिए किया जाएगा, लेकिन यह किसी धारावाहिक के लिए किसी भी प्रारूप (टेक्स्ट-आधारित या नहीं) को संभालने के लिए संभव है।

यह भी देखें

यदि आप अपने टेबल से कुछ डेटा को क्रमबद्ध रूप में प्राप्त करना चाहते हैं, तो आप dumpdata प्रबंधन कमांड का उपयोग कर सकते हैं।

सीरियलाइज़िंग डेटा

उच्चतम स्तर पर, क्रमबद्ध डेटा एक बहुत ही सरल ऑपरेशन है:

from django.core import serializers
data = serializers.serialize("xml", SomeModel.objects.all())

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

django.core.serializers.get_serializer(format)

आप सीधे एक सीरलाइज़र ऑब्जेक्ट का भी उपयोग कर सकते हैं:

XMLSerializer = serializers.get_serializer("xml")
xml_serializer = XMLSerializer()
xml_serializer.serialize(queryset)
data = xml_serializer.getvalue()

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

with open("file.xml", "w") as out:
    xml_serializer.serialize(SomeModel.objects.all(), stream=out)

ध्यान दें

अज्ञात format get_serializer() को कॉल get_serializer() django.core.serializers.SerializerDoesNotExist अपवाद को django.core.serializers.SerializerDoesNotExist

खेतों की सबसेट

यदि आप केवल फ़ील्ड का एक सबसेट क्रमबद्ध करना चाहते हैं, तो आप सीरियल तर्क के लिए fields तर्क निर्दिष्ट कर सकते हैं:

from django.core import serializers
data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size'))

इस उदाहरण में, प्रत्येक मॉडल के केवल name और size विशेषताओं को क्रमबद्ध किया जाएगा। प्राथमिक कुंजी हमेशा परिणामी आउटपुट में pk तत्व के रूप में क्रमबद्ध होती है; यह fields हिस्से में कभी नहीं दिखाई देता है।

ध्यान दें

अपने मॉडल के आधार पर, आप पा सकते हैं कि किसी मॉडल को डिसेर्बलाइज करना संभव नहीं है जो केवल अपने क्षेत्रों के सबसेट को क्रमबद्ध करता है। यदि कोई अनुक्रमित ऑब्जेक्ट किसी मॉडल द्वारा आवश्यक सभी फ़ील्ड निर्दिष्ट नहीं करता है, तो deserializer deserialized उदाहरणों को सहेजने में सक्षम नहीं होगा।

निहित मॉडल

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

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

class Place(models.Model):
    name = models.CharField(max_length=50)

class Restaurant(Place):
    serves_hot_dogs = models.BooleanField(default=False)

यदि आप केवल रेस्तरां मॉडल को क्रमबद्ध करते हैं:

data = serializers.serialize('xml', Restaurant.objects.all())

क्रमबद्ध आउटपुट पर फ़ील्ड में serves_hot_dogs विशेषताएँ होती हैं। आधार वर्ग के name विशेषता को नजरअंदाज कर दिया जाएगा।

अपने Restaurant उदाहरणों को पूरी तरह से क्रमबद्ध करने के लिए, आपको Place मॉडल को भी क्रमबद्ध करना होगा:

all_objects = list(Restaurant.objects.all()) + list(Place.objects.all())
data = serializers.serialize('xml', all_objects)

Deserializing डेटा

Deserializing डेटा भी एक काफी सरल ऑपरेशन है:

for obj in serializers.deserialize("xml", data):
    do_something_with(obj)

जैसा कि आप देख सकते हैं, deserialize फ़ंक्शन समान प्रारूप तर्क लेता है जैसे कि serialize , एक स्ट्रिंग या डेटा की धारा, और एक पुनरावृत्ति देता है।

हालांकि, यहां यह थोड़ा जटिल हो जाता है। वस्तुओं को deserialize द्वारा लौटाए जाने वाले साधारण Django ऑब्जेक्ट नहीं हैं। इसके बजाय, वे विशेष DeserializedObject उदाहरण हैं जो एक निर्मित - लेकिन बिना सहेजे - ऑब्जेक्ट और किसी भी संबद्ध संबंध डेटा को लपेटते हैं।

DeserializedObject.save() कॉलिंग ऑब्जेक्ट को डेटाबेस में बचाता है।

ध्यान दें

यदि क्रमबद्ध डेटा में pk विशेषता मौजूद नहीं है या अशक्त है, तो डेटाबेस में एक नया उदाहरण सहेजा जाएगा।

यह सुनिश्चित करता है कि deserializing एक गैर-विनाशकारी ऑपरेशन है, भले ही आपके क्रमबद्ध प्रतिनिधित्व में डेटा डेटाबेस में वर्तमान में मौजूद मैच से मेल नहीं खाता हो। आमतौर पर, इन DeserializedObject उदाहरणों के साथ काम करना कुछ इस तरह दिखता है:

for deserialized_object in serializers.deserialize("xml", data):
    if object_should_be_saved(deserialized_object):
        deserialized_object.save()

दूसरे शब्दों में, सामान्य उपयोग deserialized वस्तुओं की जांच करने के लिए सुनिश्चित करने के लिए है कि वे ऐसा करने से पहले बचत के लिए "उपयुक्त" हैं। बेशक, अगर आपको अपने डेटा स्रोत पर भरोसा है, तो आप ऑब्जेक्ट को बचा सकते हैं और आगे बढ़ सकते हैं।

Django ऑब्जेक्ट को deserialized_object.object रूप में निरीक्षण किया जा सकता है। यदि सीरियल किए गए डेटा में फ़ील्ड किसी मॉडल पर मौजूद नहीं हैं, तो एक DeserializationError को उठाया जाएगा जब तक कि ignorenonexistent तर्क को True रूप में पारित नहीं किया जाता है:

serializers.deserialize("xml", data, ignorenonexistent=True)

सरलीकरण प्रारूप

Django कई सीरियल प्रारूपणों का समर्थन करता है, जिनमें से कुछ को आपको तृतीय-पक्ष पायथन मॉड्यूल स्थापित करने की आवश्यकता होती है:

पहचानकर्ता जानकारी
xml एक सरल XML बोली से और उससे संबंधित है।
json JSON से और इसके लिए सीरियल करता है।
yaml YAML (YAML A मार्कआउट लैंग्वेज नहीं है) के लिए सीरियल करता है। यह धारावाहिक केवल तभी उपलब्ध है यदि PyYAML स्थापित है।

एक्सएमएल

मूल XML क्रमांकन प्रारूप काफी सरल है:

<?xml version="1.0" encoding="utf-8"?>
<django-objects version="1.0">
    <object pk="123" model="sessions.session">
        <field type="DateTimeField" name="expire_date">2013-01-16T08:16:59.844560+00:00</field>
        <!-- ... -->
    </object>
</django-objects>

वस्तुओं का पूरा संग्रह जो या तो क्रमबद्ध या deserialized है, एक <django-objects> Objects <django-objects> -tag द्वारा दर्शाया गया है जिसमें कई <object> -elements शामिल हैं। इस तरह की प्रत्येक वस्तु की दो विशेषताएँ होती हैं: "pk" और "मॉडल", बाद वाले को एप्लिकेशन ("सत्र") के नाम से दर्शाया जा रहा है और एक डॉट द्वारा अलग किए गए मॉडल ("सत्र") का निचला नाम।

ऑब्जेक्ट के प्रत्येक क्षेत्र को "फ़ील्ड" और "नाम" जैसे क्षेत्रों को स्पोर्ट करने वाले <field> -मेंट के रूप में क्रमबद्ध किया जाता है। तत्व की पाठ सामग्री उस मूल्य का प्रतिनिधित्व करती है जिसे संग्रहीत किया जाना चाहिए।

विदेशी कुंजियों और अन्य संबंध क्षेत्रों को थोड़ा अलग तरह से व्यवहार किया जाता है:

<object pk="27" model="auth.permission">
    <!-- ... -->
    <field to="contenttypes.contenttype" name="content_type" rel="ManyToOneRel">9</field>
    <!-- ... -->
</object>

इस उदाहरण में हम निर्दिष्ट करते हैं कि PK। 27 के साथ auth.Permission ऑब्जेक्ट contenttypes.ContentType उदाहरण PK 9 के साथ एक विदेशी कुंजी है।

कईटोमनी-संबंधों को उस मॉडल के लिए निर्यात किया जाता है जो उन्हें बांधता है। उदाहरण के लिए, auth.User मॉडल मॉडल में इस तरह का संबंध है।

<object pk="1" model="auth.user">
    <!-- ... -->
    <field to="auth.permission" name="user_permissions" rel="ManyToManyRel">
        <object pk="46"></object>
        <object pk="47"></object>
    </field>
</object>

यह उदाहरण दिए गए उपयोगकर्ता को PKs 46 और 47 के साथ अनुमति मॉडल से जोड़ता है।

पात्रों पर नियंत्रण रखें

यदि धारावाहिकीकृत की जाने वाली सामग्री में नियंत्रण वर्ण होते हैं जो XML 1.0 मानक में स्वीकार नहीं किए जाते हैं, तो मान का अपवाद के साथ क्रमांकन विफल हो जाएगा। W3C की HTML, XHTML, XML और कंट्रोल कोड की व्याख्या भी पढ़ें।

JSON

जब एक ही उदाहरण डेटा के साथ रहने से पहले इसे JSON के रूप में क्रमबद्ध किया जाएगा:

[
    {
        "pk": "4b678b301dfd8a4e0dad910de3ae245b",
        "model": "sessions.session",
        "fields": {
            "expire_date": "2013-01-16T08:16:59.844Z",
            ...
        }
    }
]

यहाँ स्वरूपण XML के साथ की तुलना में थोड़ा सरल है। पूरे संग्रह को एक सरणी के रूप में दर्शाया गया है और वस्तुओं को तीन गुणों के साथ JSON ऑब्जेक्ट द्वारा दर्शाया गया है: "pk", "मॉडल" और "फ़ील्ड"। "फ़ील्ड" फिर से एक फ़ील्ड है जिसमें क्रमशः प्रत्येक फ़ील्ड का नाम और मूल्य संपत्ति और संपत्ति-मूल्य के रूप में होता है।

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

ध्यान रखें कि सभी Django आउटपुट को json अनधिकृत रूप से पारित नहीं किया जा सकता है। उदाहरण के लिए, यदि आपके पास क्रमबद्ध होने के लिए कुछ कस्टम प्रकार है, तो आपको इसके लिए एक कस्टम json एनकोडर लिखना होगा। कुछ इस तरह काम करेगा:

from django.core.serializers.json import DjangoJSONEncoder

class LazyEncoder(DjangoJSONEncoder):
    def default(self, obj):
        if isinstance(obj, YourCustomType):
            return str(obj)
        return super().default(obj)

फिर आप cls=LazyEncoder को serializers.serialize() फ़ंक्शन से पास कर सकते हैं:

from django.core.serializers import serialize

serialize('json', SomeModel.objects.all(), cls=LazyEncoder)

यह भी ध्यान दें कि GeoDjango एक अनुकूलित GeoJSON serializer प्रदान करता है।

DjangoJSONEncoder

class django.core.serializers.json.DjangoJSONEncoder

JSON धारावाहिक एन्कोडिंग के लिए DjangoJSONEncoder का उपयोग करता है। JSONEncoder का एक उपवर्ग, यह इन अतिरिक्त प्रकारों को संभालता है:

datetime
प्रपत्र YYYY-MM-DDTHH:mm:ss.sssZ या YYYY-MM-DDTHH:mm:ss.sss+HH:MM को ECMA-262 में परिभाषित किया गया है।
date
ECMA-262 में परिभाषित YYYY-MM-DD फॉर्म की एक स्ट्रिंग।
time
HH:MM:ss.sss में परिभाषित HH:MM:ss.sss की एक स्ट्रिंग।
timedelta
आईएसओ -8601 में परिभाषित एक स्ट्रिंग एक अवधि का प्रतिनिधित्व करती है। उदाहरण के लिए, timedelta(days=1, hours=2, seconds=3.4) को 'P1DT02H00M03.400000S' रूप में 'P1DT02H00M03.400000S'
Decimal, Promise (django.utils.functional.lazy() objects), UUID
ऑब्जेक्ट का एक स्ट्रिंग प्रतिनिधित्व।

YAML

YAML क्रमांकन JSON के समान दिखता है। ऑब्जेक्ट सूची को अनुक्रम "पीके", "मॉडल" और "फ़ील्ड" के साथ अनुक्रम मैपिंग के रूप में क्रमबद्ध किया जाता है। प्रत्येक फ़ील्ड फिर से एक मैपिंग है जिसमें क्षेत्र का नाम और मूल्य का महत्व है:

-   fields: {expire_date: !!timestamp '2013-01-16 08:16:59.844560+00:00'}
    model: sessions.session
    pk: 4b678b301dfd8a4e0dad910de3ae245b

रेफ़रेंशियल फ़ील्ड्स को फिर से पीके या पीके के अनुक्रम द्वारा दर्शाया जाता है।

प्राकृतिक कुंजी

विदेशी कुंजी और कई-से-कई संबंधों के लिए डिफ़ॉल्ट क्रमांकन रणनीति संबंध में वस्तुओं की प्राथमिक कुंजी (एस) के मूल्य को क्रमबद्ध करना है। यह रणनीति ज्यादातर वस्तुओं के लिए अच्छी तरह से काम करती है, लेकिन यह कुछ परिस्थितियों में कठिनाई पैदा कर सकती है।

उन वस्तुओं की सूची के मामले पर विचार करें जिनके पास एक विदेशी कुंजी सन्दर्भ है ContentType । यदि आप एक ऐसी वस्तु को क्रमबद्ध करने जा रहे हैं, जो एक सामग्री प्रकार को संदर्भित करती है, तो आपको उस सामग्री प्रकार को संदर्भित करने के लिए एक तरीका होना चाहिए, जिसके साथ शुरू करना है। चूंकि ContentType ऑब्जेक्ट डेटाबेस सिंक्रनाइज़ेशन प्रक्रिया के दौरान Django द्वारा स्वचालित रूप से बनाए जाते हैं, किसी दिए गए सामग्री प्रकार की प्राथमिक कुंजी का अनुमान लगाना आसान नहीं है; यह इस बात पर निर्भर करेगा कि migrate कब और कैसे किया गया। यह उन सभी मॉडलों के लिए सच है जो स्वचालित रूप से वस्तुओं को उत्पन्न करते हैं, विशेष रूप से Permission , Group और User सहित।

चेतावनी

आपको कभी भी किसी फिक्स्ड या अन्य सीरियल किए गए डेटा में स्वचालित रूप से जेनरेट की गई वस्तुओं को शामिल नहीं करना चाहिए। संयोग से, फ़िक्चर में प्राथमिक कुंजियाँ डेटाबेस में मेल खा सकती हैं और फ़िक्सचर लोड करने का कोई प्रभाव नहीं पड़ेगा। अधिक संभावित मामले में जो वे मेल नहीं खाते हैं, फ़िक्चर लोडिंग एक IntegrityError साथ विफल हो जाएगी।

सुविधा की बात भी है। एक पूर्णांक आईडी हमेशा किसी वस्तु को संदर्भित करने का सबसे सुविधाजनक तरीका नहीं है; कभी-कभी, एक अधिक प्राकृतिक संदर्भ सहायक होगा।

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

प्राकृतिक कुंजियों का वर्णन

निम्नलिखित दो मॉडल पर विचार करें:

from django.db import models

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

    birthdate = models.DateField()

    class Meta:
        unique_together = (('first_name', 'last_name'),)

class Book(models.Model):
    name = models.CharField(max_length=100)
    author = models.ForeignKey(Person, on_delete=models.CASCADE)

आमतौर पर, Book क्रमबद्ध डेटा लेखक को संदर्भित करने के लिए पूर्णांक का उपयोग करेगा। उदाहरण के लिए, JSON में, एक पुस्तक को क्रमबद्ध किया जा सकता है:

...
{
    "pk": 1,
    "model": "store.book",
    "fields": {
        "name": "Mostly Harmless",
        "author": 42
    }
}
...

यह एक लेखक को संदर्भित करने के लिए एक विशेष रूप से प्राकृतिक तरीका नहीं है। इसके लिए आवश्यक है कि आप लेखक के लिए प्राथमिक मुख्य मूल्य जानते हों; इसके लिए यह भी आवश्यक है कि यह प्राथमिक कुंजी मान स्थिर और पूर्वानुमान योग्य हो।

हालांकि, यदि हम व्यक्ति को प्राकृतिक कुंजी हैंडलिंग जोड़ते हैं, तो स्थिरता बहुत अधिक मानवीय हो जाती है। प्राकृतिक कुंजी हैंडलिंग को जोड़ने के लिए, आप एक डिफ़ॉल्ट प्रबंधक को एक get_by_natural_key() विधि के साथ व्यक्ति के लिए परिभाषित करते हैं। एक व्यक्ति के मामले में, एक अच्छी प्राकृतिक कुंजी पहले और अंतिम नाम की जोड़ी हो सकती है:

from django.db import models

class PersonManager(models.Manager):
    def get_by_natural_key(self, first_name, last_name):
        return self.get(first_name=first_name, last_name=last_name)

class Person(models.Model):
    objects = PersonManager()

    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    birthdate = models.DateField()

    class Meta:
        unique_together = (('first_name', 'last_name'),)

अब पुस्तकें व्यक्तिगत वस्तुओं को संदर्भित करने के लिए उस प्राकृतिक कुंजी का उपयोग कर सकती हैं:

...
{
    "pk": 1,
    "model": "store.book",
    "fields": {
        "name": "Mostly Harmless",
        "author": ["Douglas", "Adams"]
    }
}
...

जब आप इस क्रमबद्ध डेटा को लोड करने का प्रयास करते हैं, तो Django एक वास्तविक Person वस्तु के प्राथमिक कुंजी में ["Douglas", "Adams"] को हल करने के लिए get_by_natural_key() विधि का उपयोग करेगा।

ध्यान दें

प्राकृतिक कुंजी के लिए आप जो भी फ़ील्ड उपयोग करते हैं, वह किसी वस्तु को विशिष्ट रूप से पहचानने में सक्षम होना चाहिए। इसका आमतौर पर मतलब होगा कि आपकी प्राकृतिक कुंजी में फ़ील्ड या फ़ील्ड के लिए आपके मॉडल में एक अद्वितीय क्लॉज़ होगा (या तो एकल फ़ील्ड पर या = unique_together से कई क्षेत्रों में अद्वितीय)। हालाँकि, विशिष्टता को डेटाबेस स्तर पर लागू करने की आवश्यकता नहीं है। यदि आप निश्चित हैं कि खेतों का एक सेट प्रभावी रूप से अद्वितीय होगा, तो आप अभी भी उन क्षेत्रों को एक प्राकृतिक कुंजी के रूप में उपयोग कर सकते हैं।

बिना किसी प्राथमिक कुंजी वाली वस्तुओं का get_by_natural_key() हमेशा यह जांच करेगा कि मॉडल के प्रबंधक के पास एक get_by_natural_key() विधि है और यदि ऐसा है, तो इसे deserialized ऑब्जेक्ट की प्राथमिक कुंजी को पॉप्युलेट करने के लिए उपयोग करें।

प्राकृतिक कुंजी का सीरियलाइजेशन

तो कैसे आप Django प्राप्त करते हैं जब एक प्राकृतिक धारावाहिक एक वस्तु धारावाहिक? सबसे पहले, आपको एक और विधि जोड़ने की आवश्यकता है - इस बार मॉडल में ही:

class Person(models.Model):
    objects = PersonManager()

    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    birthdate = models.DateField()

    def natural_key(self):
        return (self.first_name, self.last_name)

    class Meta:
        unique_together = (('first_name', 'last_name'),)

इस विधि को हमेशा एक प्राकृतिक कुंजी टपल लौटना चाहिए - इस उदाहरण में, (first name, last name) । फिर, जब आप serializers.serialize() कॉल करते हैं, तो आप use_natural_foreign_keys=True या use_natural_primary_keys=True तर्क प्रदान करते हैं:

>>> serializers.serialize('json', [book1, book2], indent=2,
...      use_natural_foreign_keys=True, use_natural_primary_keys=True)

जब use_natural_foreign_keys=True निर्दिष्ट किया जाता है, तो Django use_natural_foreign_keys=True natural_key() विधि का उपयोग किसी भी प्रकार के विदेशी कुंजी संदर्भ को क्रमबद्ध करने के लिए करेगा जो विधि को परिभाषित करता है।

जब use_natural_primary_keys=True निर्दिष्ट किया जाता है, तो Django इस ऑब्जेक्ट के क्रमबद्ध डेटा में प्राथमिक कुंजी प्रदान नहीं करेगा, क्योंकि इसकी गणना deserialization के दौरान की जा सकती है:

...
{
    "model": "store.person",
    "fields": {
        "first_name": "Douglas",
        "last_name": "Adams",
        "birth_date": "1952-03-11",
    }
}
...

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

यदि आप क्रमबद्ध डेटा उत्पन्न करने के लिए dumpdata --natural-foreign का उपयोग कर रहे हैं, तो dumpdata --natural-foreign और dumpdata --natural-primary प्राकृतिक dumpdata --natural-primary कमांड लाइन के झंडे का उपयोग प्राकृतिक कुंजी उत्पन्न करने के लिए करें।

ध्यान दें

आपको get_by_natural_key() और get_by_natural_key() दोनों को परिभाषित करने की आवश्यकता नहीं है। यदि आप Django को क्रमिककरण के दौरान प्राकृतिक कुंजियों का उत्पादन नहीं करना चाहते हैं, लेकिन आप प्राकृतिक कुंजियों को लोड करने की क्षमता बनाए रखना चाहते हैं, तो आप natural_key() पद्धति को लागू नहीं करने का विकल्प चुन सकते हैं।

इसके विपरीत, यदि (कुछ विचित्र कारण के लिए) आप चाहते हैं कि Django सीरियलाइज़ेशन के दौरान प्राकृतिक कुंजियों का उत्पादन करे, लेकिन उन प्रमुख मूल्यों को लोड करने में सक्षम नहीं है, तो बस get_by_natural_key() विधि को परिभाषित न करें।

क्रमबद्धता के दौरान निर्भरता

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

इस सीमा को समायोजित करने के लिए, dumpdata --natural-foreign को कॉल करने वाले dumpdata --natural-foreign विकल्प मानक प्राथमिक कुंजी वस्तुओं को dumpdata --natural-foreign करने से पहले एक natural_key() विधि के साथ किसी भी मॉडल को क्रमबद्ध करेंगे।

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

इस आदेश को नियंत्रित करने के लिए, आप अपने natural_key() विधियों पर निर्भरता को परिभाषित कर सकते हैं। आप इसे natural_key() विधि पर dependencies विशेषता सेट करके करते हैं।

उदाहरण के लिए, ऊपर के उदाहरण से Book मॉडल में एक प्राकृतिक कुंजी जोड़ें:

class Book(models.Model):
    name = models.CharField(max_length=100)
    author = models.ForeignKey(Person, on_delete=models.CASCADE)

    def natural_key(self):
        return (self.name,) + self.author.natural_key()

Book लिए प्राकृतिक कुंजी इसके नाम और इसके लेखक का एक संयोजन है। इसका मतलब है कि Person को Book से पहले क्रमबद्ध होना चाहिए। इस निर्भरता को परिभाषित करने के लिए, हम एक अतिरिक्त पंक्ति जोड़ते हैं:

def natural_key(self):
    return (self.name,) + self.author.natural_key()
natural_key.dependencies = ['example_app.person']

यह परिभाषा सुनिश्चित करती है कि सभी Person वस्तुओं को किसी भी Book वस्तुओं से पहले क्रमबद्ध किया जाए। बदले में, किसी भी ऑब्जेक्ट रेफरेंस Book को Person और Book दोनों के सीरियल किए जाने के बाद सीरियल किया जाएगा।