Django 2.1

Models




django

Models

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

मूल बातें:

  • प्रत्येक मॉडल एक पायथन वर्ग है जो django.db.models.Model
  • मॉडल की प्रत्येक विशेषता एक डेटाबेस फ़ील्ड का प्रतिनिधित्व करती है।
  • इस सब के साथ, Django आपको स्वचालित रूप से उत्पन्न डेटाबेस-एक्सेस एपीआई देता है; प्रश्न बनाना देखें।

त्वरित उदाहरण

यह उदाहरण मॉडल एक Person को परिभाषित करता है, जिसके पास first_name और last_name :

from django.db import models

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

first_name और last_name मॉडल के fields हैं। प्रत्येक फ़ील्ड को वर्ग विशेषता के रूप में निर्दिष्ट किया जाता है, और प्रत्येक विशेषता डेटाबेस कॉलम में मैप करता है।

उपरोक्त Person मॉडल इस तरह एक डेटाबेस तालिका बनाएगा:

CREATE TABLE myapp_person (
    "id" serial NOT NULL PRIMARY KEY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);

कुछ तकनीकी नोट:

  • तालिका का नाम, myapp_person , स्वचालित रूप से कुछ मॉडल मेटाडेटा से लिया गया है, लेकिन इसे ओवरराइड किया जा सकता है। अधिक विवरण के लिए तालिका नाम देखें।
  • एक id फ़ील्ड स्वचालित रूप से जोड़ दी जाती है, लेकिन इस व्यवहार को ओवरराइड किया जा सकता है। स्वचालित प्राथमिक कुंजी फ़ील्ड देखें।
  • इस उदाहरण में CREATE TABLE SQL को PostgreSQL सिंटैक्स का उपयोग करके स्वरूपित किया गया है, लेकिन यह ध्यान देने योग्य है कि Django आपकी सेटिंग फ़ाइल में निर्दिष्ट डेटाबेस बैकएंड के अनुरूप SQL का उपयोग करता है।

मॉडल का उपयोग करना

एक बार जब आप अपने मॉडलों को परिभाषित कर लेते हैं, तो आपको Django को बताने की आवश्यकता है कि आप उन मॉडलों का उपयोग करने जा रहे हैं। अपनी सेटिंग फ़ाइल को संपादित करके और INSTALLED_APPS सेटिंग को बदलकर अपने models.py का मॉड्यूल शामिल करें।

उदाहरण के लिए, यदि आपके एप्लिकेशन के लिए मॉडल मॉड्यूल myapp.models में रहते हैं (पैकेज संरचना जो कि myapp.models स्क्रिप्ट द्वारा किसी एप्लिकेशन के लिए बनाई गई है), INSTALLED_APPS को पढ़ना चाहिए, भाग में:

INSTALLED_APPS = [
    #...
    'myapp',
    #...
]

जब आप INSTALLED_APPS नए ऐप जोड़ते manage.py migrate , तो manage.py makemigrations manage.py migrate चलाना सुनिश्चित करें, वैकल्पिक रूप से उनके लिए सबसे पहले माइग्रेशन बनाकर manage.py makemigrations

खेत

एक मॉडल का सबसे महत्वपूर्ण हिस्सा - और एक मॉडल का एकमात्र आवश्यक हिस्सा - डेटाबेस फ़ील्ड्स की सूची है जो इसे परिभाषित करता है। फ़ील्ड श्रेणी विशेषताओं द्वारा निर्दिष्ट किए जाते हैं। फ़ील्ड नामों को चुनने में सावधानी बरतें, जो मॉडल API जैसे clean , save , या delete साथ संघर्ष करते हैं।

उदाहरण:

from django.db import models

class Musician(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    instrument = models.CharField(max_length=100)

class Album(models.Model):
    artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
    name = models.CharField(max_length=100)
    release_date = models.DateField()
    num_stars = models.IntegerField()

फ़ील्ड प्रकार

आपके मॉडल में प्रत्येक फ़ील्ड उपयुक्त Field वर्ग का एक उदाहरण होना चाहिए। Django कुछ चीजों को निर्धारित करने के लिए फ़ील्ड वर्ग प्रकारों का उपयोग करता है:

  • कॉलम प्रकार, जो डेटाबेस को बताता है कि किस तरह के डेटा को स्टोर करना है (जैसे INTEGER , VARCHAR , TEXT )।
  • प्रपत्र फ़ील्ड प्रदान करते समय उपयोग करने के लिए डिफ़ॉल्ट HTML widget (उदाहरण <input type="text"> , <select> )।
  • Django के व्यवस्थापक और स्वचालित रूप से जनरेट किए गए प्रपत्रों में उपयोग की जाने वाली न्यूनतम सत्यापन आवश्यकताएं।

दर्जनों बिल्ट-इन फ़ील्ड प्रकारों के साथ Django के जहाज; आप मॉडल फ़ील्ड संदर्भ में पूरी सूची पा सकते हैं। यदि Django के अंतर्निहित लोग चाल नहीं करते हैं तो आप आसानी से अपने खुद के फ़ील्ड लिख सकते हैं; कस्टम मॉडल फ़ील्ड लिखना

क्षेत्र विकल्प

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

सभी फ़ील्ड प्रकारों के लिए उपलब्ध सामान्य तर्कों का एक सेट भी है। सभी वैकल्पिक हैं। उन्हें reference में पूरी तरह से समझाया गया है, लेकिन यहां सबसे अधिक उपयोग किए जाने वाले त्वरित सारांश हैं:

null
यदि True , तो Django डेटाबेस में रिक्त मान को NULL रूप में संग्रहीत करेगा। डिफ़ॉल्ट False
blank

यदि True , तो फ़ील्ड रिक्त होने की अनुमति है। डिफ़ॉल्ट False

ध्यान दें कि यह null से अलग है। null विशुद्ध रूप से डेटाबेस से संबंधित है, जबकि blank सत्यापन से संबंधित है। यदि किसी फ़ील्ड में blank , तो प्रपत्र सत्यापन रिक्त मान के प्रवेश की अनुमति देगा। यदि किसी फ़ील्ड में blank , तो फ़ील्ड की आवश्यकता होगी।

choices

इस क्षेत्र के विकल्पों के रूप में उपयोग करने के लिए 2-टुपल्स का एक पुनरावृत्त (उदाहरण, एक सूची या टुपल)। यदि यह दिया जाता है, तो डिफ़ॉल्ट रूप विजेट मानक टेक्स्ट फ़ील्ड के बजाय एक चयनित बॉक्स होगा और विकल्पों को दिए गए विकल्पों तक सीमित कर देगा।

एक विकल्प सूची इस तरह दिखती है:

YEAR_IN_SCHOOL_CHOICES = (
    ('FR', 'Freshman'),
    ('SO', 'Sophomore'),
    ('JR', 'Junior'),
    ('SR', 'Senior'),
    ('GR', 'Graduate'),
)

प्रत्येक टपल में पहला तत्व वह मान है जो डेटाबेस में संग्रहीत किया जाएगा। दूसरा तत्व फ़ील्ड के फॉर्म विजेट द्वारा प्रदर्शित किया जाता है।

एक मॉडल उदाहरण को देखते हुए, choices साथ एक फ़ील्ड के लिए प्रदर्शन मान को get_FOO_display() विधि का उपयोग करके एक्सेस किया जा सकता है। उदाहरण के लिए:

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=1, choices=SHIRT_SIZES)
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'
default
फ़ील्ड के लिए डिफ़ॉल्ट मान। यह एक मूल्य या एक कॉल करने योग्य वस्तु हो सकती है। यदि कॉल करने योग्य है तो हर बार एक नई वस्तु बनाई जाएगी।
help_text
प्रपत्र विजेट के साथ प्रदर्शित करने के लिए अतिरिक्त "सहायता" पाठ। यदि आपके फ़ील्ड का उपयोग किसी प्रपत्र पर नहीं किया गया है, तो भी यह प्रलेखन के लिए उपयोगी है।
primary_key

यदि True , तो यह फ़ील्ड मॉडल की प्राथमिक कुंजी है।

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

प्राथमिक कुंजी फ़ील्ड केवल-पढ़ने के लिए है। यदि आप किसी मौजूदा ऑब्जेक्ट पर प्राथमिक कुंजी का मान बदलते हैं और फिर उसे सहेजते हैं, तो पुराने के साथ एक नई ऑब्जेक्ट बनाई जाएगी। उदाहरण के लिए:

from django.db import models

class Fruit(models.Model):
    name = models.CharField(max_length=100, primary_key=True)
>>> fruit = Fruit.objects.create(name='Apple')
>>> fruit.name = 'Pear'
>>> fruit.save()
>>> Fruit.objects.values_list('name', flat=True)
<QuerySet ['Apple', 'Pear']>
unique
यदि True , तो यह फ़ील्ड पूरे तालिका में अद्वितीय होनी चाहिए।

फिर से, ये सबसे सामान्य क्षेत्र विकल्पों का संक्षिप्त वर्णन है। पूर्ण विवरण reference में पाया जा सकता है।

स्वचालित प्राथमिक कुंजी फ़ील्ड

डिफ़ॉल्ट रूप से, Django प्रत्येक मॉडल को निम्न फ़ील्ड देता है:

id = models.AutoField(primary_key=True)

यह एक ऑटो-इन्क्रिमिंग प्राथमिक कुंजी है।

यदि आप एक कस्टम प्राथमिक कुंजी निर्दिष्ट करना चाहते हैं, तो अपने किसी फ़ील्ड पर प्राथमिक_की primary_key निर्दिष्ट करें। अगर Django देखता है कि आपने स्पष्ट रूप से primary_key सेट primary_key , तो यह स्वचालित id कॉलम नहीं जोड़ेगा।

प्रत्येक मॉडल के लिए primary_key से एक फ़ील्ड होना चाहिए primary_key (या तो स्पष्ट रूप से घोषित या स्वचालित रूप से जोड़ा गया)।

क्रिया क्षेत्र के नाम

प्रत्येक फ़ील्ड प्रकार, OneToOneField , OneToOneField और OneToOneField , एक वैकल्पिक पहला स्थिति तर्क - एक OneToOneField नाम लेता है। यदि क्रिया नाम नहीं दिया गया है, तो Django स्वचालित रूप से फ़ील्ड के विशेषता नाम का उपयोग करके इसे बनाएगा, जो अंडरस्कोर को रिक्त स्थान में परिवर्तित करेगा।

इस उदाहरण में, क्रिया का नाम "person's first name" :

first_name = models.CharField("person's first name", max_length=30)

इस उदाहरण में, क्रिया का नाम "first name" :

first_name = models.CharField(max_length=30)

ForeignKey , OneToOneField और OneToOneField को मॉडल वर्ग होने के लिए पहले तर्क की आवश्यकता होती है, इसलिए verbose_name कीवर्ड तर्क का उपयोग करें:

poll = models.ForeignKey(
    Poll,
    on_delete=models.CASCADE,
    verbose_name="the related poll",
)
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(
    Place,
    on_delete=models.CASCADE,
    verbose_name="related place",
)

कन्वेंशन verbose_name के पहले अक्षर को कैपिटलाइज़ नहीं करना है। Django स्वचालित रूप से पहले अक्षर को कैपिटल करेगा जहां इसे करने की आवश्यकता है।

रिश्तों

स्पष्ट रूप से, रिलेशनल डेटाबेस की शक्ति एक दूसरे से संबंधित तालिकाओं में निहित है। Django तीन सबसे सामान्य प्रकार के डेटाबेस संबंधों को परिभाषित करने के तरीके प्रदान करता है: कई-से-एक, कई-से-कई और एक-से-एक।

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

कई-से-एक संबंध को परिभाषित करने के लिए, ForeignKey उपयोग ForeignKey । आप इसे किसी भी अन्य Field प्रकार की तरह उपयोग करते हैं: इसे अपने मॉडल के वर्ग विशेषता के रूप में शामिल करके।

ForeignKey को एक ForeignKey तर्क की आवश्यकता है: वह वर्ग जिससे मॉडल संबंधित है।

उदाहरण के लिए, अगर एक Car मॉडल में एक Manufacturer - अर्थात, एक Manufacturer कई कारें बनाता है, लेकिन प्रत्येक Car केवल एक Manufacturer - निम्नलिखित परिभाषा का उपयोग करें:

from django.db import models

class Manufacturer(models.Model):
    # ...
    pass

class Car(models.Model):
    manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
    # ...

आप पुनरावर्ती संबंध भी बना सकते हैं (स्वयं के लिए कई-से-एक संबंध के साथ एक वस्तु) और अभी तक परिभाषित नहीं किए गए मॉडल के लिए संबंध ; विवरण के लिए मॉडल फ़ील्ड संदर्भ देखें।

यह सुझाव दिया गया है, लेकिन आवश्यक नहीं है, कि ForeignKey फील्ड (ऊपर दिए गए उदाहरण में manufacturer ) का नाम मॉडल, लोअरकेस का नाम हो। आप निश्चित रूप से, फ़ील्ड को कॉल कर सकते हैं जो आप चाहते हैं। उदाहरण के लिए:

class Car(models.Model):
    company_that_makes_it = models.ForeignKey(
        Manufacturer,
        on_delete=models.CASCADE,
    )
    # ...

यह भी देखें

ForeignKey फ़ील्ड कई अतिरिक्त तर्क स्वीकार करते हैं जिन्हें मॉडल फ़ील्ड संदर्भ में समझाया गया है । ये विकल्प परिभाषित करने में मदद करते हैं कि रिश्ते को कैसे काम करना चाहिए; सभी वैकल्पिक हैं।

पीछे से संबंधित वस्तुओं तक पहुंचने के विवरण के लिए, निम्नलिखित रिश्तों को पीछे की ओर देखें

नमूना कोड के लिए, कई-से-एक संबंध मॉडल उदाहरण देखें

कई-कई रिश्ते

कई-से-कई संबंधों को परिभाषित करने के लिए, ManyToManyField का ManyToManyField । आप इसे किसी भी अन्य Field प्रकार की तरह उपयोग करते हैं: इसे अपने मॉडल के वर्ग विशेषता के रूप में शामिल करके।

ManyToManyField को एक ManyToManyField तर्क की आवश्यकता होती है: वह वर्ग जिससे मॉडल संबंधित है।

उदाहरण के लिए, यदि Pizza में कई Topping ऑब्जेक्ट हैं - यानी, Topping कई पिज्जा पर हो सकती है और प्रत्येक Pizza में कई टॉपिंग होते हैं - यहां बताया गया है कि आप इसका प्रतिनिधित्व कैसे करेंगे:

from django.db import models

class Topping(models.Model):
    # ...
    pass

class Pizza(models.Model):
    # ...
    toppings = models.ManyToManyField(Topping)

ForeignKey साथ, आप पुनरावर्ती संबंध भी बना सकते हैं (स्वयं के लिए कई-से-कई संबंधों के साथ एक वस्तु) और अभी तक परिभाषित नहीं किए गए मॉडल के लिए संबंध

यह सुझाव दिया गया है, लेकिन इसकी आवश्यकता नहीं है, कि एक ManyToManyField (ऊपर दिए गए उदाहरण में toppings ) का नाम संबंधित मॉडल वस्तुओं के सेट का वर्णन करने वाला एक बहुवचन है।

इससे कोई फर्क नहीं पड़ता कि किस मॉडल में कई ManyToManyField , लेकिन आपको इसे केवल एक मॉडल में रखना चाहिए - दोनों में नहीं।

सामान्यतया, ManyToManyField इंस्टेंसेस को उस ऑब्जेक्ट में जाना चाहिए जो किसी फ़ॉर्म पर संपादित होने जा रहा है। उपर्युक्त उदाहरण में, toppings Pizza ( Topping होने के बजाए pizzas ManyToManyField ) क्योंकि pizzas Topping बारे में सोचना अधिक स्वाभाविक है क्योंकि कई पिज्जा पर टॉपिंग होने से। जिस तरह से इसे ऊपर सेट किया गया है, Pizza फॉर्म उपयोगकर्ताओं को टॉपिंग का चयन करने देगा।

यह भी देखें

एक पूर्ण उदाहरण के लिए कई-से-कई संबंध मॉडल उदाहरण देखें।

ManyToManyField फ़ील्ड कई अतिरिक्त तर्क भी स्वीकार करती हैं जिन्हें मॉडल फ़ील्ड संदर्भ में समझाया गया है । ये विकल्प परिभाषित करने में मदद करते हैं कि रिश्ते को कैसे काम करना चाहिए; सभी वैकल्पिक हैं।

कई-कई रिश्तों पर अतिरिक्त क्षेत्र

जब आप सिंपल कई-से-कई रिश्तों का सामना कर रहे होते हैं जैसे कि मिक्सिंग और मैचिंग पिज्जा और टॉपिंग, एक मानक ManyToManyField आप सभी की जरूरत है। हालांकि, कभी-कभी आपको दो मॉडल के बीच के संबंध के साथ डेटा को जोड़ना पड़ सकता है।

उदाहरण के लिए, संगीतकारों को ट्रैक करने वाले एक एप्लिकेशन के मामले पर विचार करें, जो संगीतकारों का है। एक व्यक्ति और जिन समूहों के वे सदस्य हैं, उनके बीच कई-से-कई संबंध हैं, इसलिए आप इस रिश्ते का प्रतिनिधित्व करने के लिए एक ManyToManyField का उपयोग कर सकते हैं। हालाँकि, सदस्यता के बारे में बहुत कुछ है जिसे आप एकत्र करना चाहते हैं, जैसे कि वह तारीख जिस पर वह व्यक्ति समूह में शामिल हुआ था।

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

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=128)

    def __str__(self):
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

    def __str__(self):
        return self.name

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

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

मध्यवर्ती मॉडल पर कुछ प्रतिबंध हैं:

  • आपके मध्यवर्ती मॉडल में एक होना चाहिए - और स्रोत मॉडल के लिए केवल एक - विदेशी कुंजी (यह हमारे उदाहरण में Group होगा), या आपको स्पष्ट रूप से निर्दिष्ट करना चाहिए कि Django को कई ManyToManyField.through_fields का उपयोग करके संबंध के लिए उपयोग करना चाहिए। यदि आपके पास एक से अधिक विदेशी कुंजी है और through_fields निर्दिष्ट नहीं है, तो एक सत्यापन त्रुटि उठाई जाएगी। एक समान प्रतिबंध लक्ष्य मॉडल की विदेशी कुंजी पर लागू होता है (यह हमारे उदाहरण में Person होगा)।
  • एक मॉडल के लिए जो एक मध्यस्थ मॉडल के माध्यम से खुद के लिए कई-से-कई संबंध रखता है, एक ही मॉडल के लिए दो विदेशी कुंजी की अनुमति है, लेकिन उन्हें कई-से-कई संबंधों के दो (अलग) पक्षों के रूप में माना जाएगा। यदि दो से अधिक विदेशी कुंजियाँ हैं, तो आपको ऊपर के रूप में through_fields को भी निर्दिष्ट करना होगा, या एक सत्यापन त्रुटि उठाई जाएगी।
  • एक मॉडल से खुद के लिए कई-से-कई संबंधों को परिभाषित करते समय, एक मध्यस्थ मॉडल का उपयोग करते हुए, आपको symmetrical=False ( मॉडल फ़ील्ड संदर्भ देखें ) का उपयोग करना होगा

अब जब आपने अपने मध्यस्थ मॉडल ( Membership , इस मामले में) का उपयोग करने के लिए अपने कई ManyToManyField स्थापना की है, तो आप कुछ कई-से-कई रिश्ते बनाने के लिए तैयार हैं। आप मध्यवर्ती मॉडल के उदाहरण बनाकर ऐसा करते हैं:

>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
...     date_joined=date(1962, 8, 16),
...     invite_reason="Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>]>
>>> ringo.group_set.all()
<QuerySet [<Group: The Beatles>]>
>>> m2 = Membership.objects.create(person=paul, group=beatles,
...     date_joined=date(1960, 8, 1),
...     invite_reason="Wanted to form a band.")
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>

सामान्य कई-से-कई फ़ील्ड के विपरीत, आप संबंध बनाने के लिए add() , create() , या set() का उपयोग नहीं कर सकते हैं :

>>> # The following statements will not work
>>> beatles.members.add(john)
>>> beatles.members.create(name="George Harrison")
>>> beatles.members.set([john, paul, ringo, george])

क्यूं कर? आप केवल एक Person और एक Group बीच एक संबंध नहीं बना सकते हैं - आपको Membership मॉडल द्वारा आवश्यक संबंध के लिए सभी विवरण निर्दिष्ट करने की आवश्यकता है। सरल add , create और असाइनमेंट कॉल इस अतिरिक्त विवरण को निर्दिष्ट करने का एक तरीका प्रदान नहीं करते हैं। नतीजतन, वे कई-से-कई रिश्तों के लिए अक्षम होते हैं जो एक मध्यवर्ती मॉडल का उपयोग करते हैं। इस प्रकार के संबंध बनाने का एकमात्र तरीका मध्यवर्ती मॉडल के उदाहरणों को बनाना है।

समान कारणों से remove() विधि अक्षम है। उदाहरण के लिए, यदि इंटरमीडिएट मॉडल द्वारा परिभाषित तालिका के माध्यम से रिवाज (मॉडल 1, मॉडल 2 (model1, model2) जोड़ी पर विशिष्टता को लागू नहीं करता है, तो एक remove() कॉल पर्याप्त जानकारी प्रदान नहीं करेगा जिसके रूप में मध्यवर्ती मॉडल का उदाहरण हटाया जाना चाहिए:

>>> Membership.objects.create(person=ringo, group=beatles,
...     date_joined=date(1968, 9, 4),
...     invite_reason="You've been gone for a month and we miss you.")
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>, <Person: Ringo Starr>]>
>>> # This will not work because it cannot tell which membership to remove
>>> beatles.members.remove(ringo)

हालाँकि, clear() विधि का उपयोग किसी उदाहरण के लिए कई-से-कई संबंधों को निकालने के लिए किया जा सकता है:

>>> # Beatles have broken up
>>> beatles.members.clear()
>>> # Note that this deletes the intermediate model instances
>>> Membership.objects.all()
<QuerySet []>

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

# Find all the groups with a member whose name starts with 'Paul'
>>> Group.objects.filter(members__name__startswith='Paul')
<QuerySet [<Group: The Beatles>]>

जैसा कि आप एक मध्यवर्ती मॉडल का उपयोग कर रहे हैं, आप इसकी विशेषताओं पर भी प्रश्न कर सकते हैं:

# Find all the members of the Beatles that joined after 1 Jan 1961
>>> Person.objects.filter(
...     group__name='The Beatles',
...     membership__date_joined__gt=date(1961,1,1))
<QuerySet [<Person: Ringo Starr]>

यदि आपको Membership मॉडल के बारे में सीधे जानकारी प्राप्त करने की आवश्यकता है, तो आप Membership मॉडल पर सीधे सवाल उठा सकते हैं:

>>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'

एक ही जानकारी तक पहुँचने का एक और तरीका है, एक Person वस्तु से कई-से-कई उल्टे संबंधों की क्वेरी करना:

>>> ringos_membership = ringo.membership_set.get(group=beatles)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'

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

एक-से-एक संबंध को परिभाषित करने के लिए, OneToOneField उपयोग OneToOneField । आप इसे किसी भी अन्य Field प्रकार की तरह उपयोग करते हैं: इसे अपने मॉडल के वर्ग विशेषता के रूप में शामिल करके।

यह किसी वस्तु की प्राथमिक कुंजी पर सबसे अधिक उपयोगी होता है, जब वह वस्तु किसी अन्य वस्तु को किसी तरह "विस्तारित" करती है।

OneToOneField को एक OneToOneField तर्क की आवश्यकता है: वह वर्ग जिससे मॉडल संबंधित है।

उदाहरण के लिए, यदि आप "स्थानों" का डेटाबेस बना रहे थे, तो आप डेटाबेस में सुंदर मानक सामग्री जैसे पता, फोन नंबर आदि का निर्माण करेंगे। फिर, यदि आप अपने आप को दोहराने के बजाय और Restaurant मॉडल में उन क्षेत्रों की प्रतिकृति बनाने के स्थान पर रेस्तरां के डेटाबेस का निर्माण करना चाहते थे, तो आप Restaurant को OneToOneField से Place (क्योंकि एक रेस्तरां "एक" जगह है;) वास्तव में, इसे संभालने के लिए आप आमतौर पर inheritance उपयोग करेंगे, जिसमें निहित एक से एक संबंध शामिल हैं)।

ForeignKey साथ, एक पुनरावर्ती संबंध को परिभाषित किया जा सकता है और अभी तक अपरिभाषित मॉडल के संदर्भ बनाए जा सकते हैं।

यह भी देखें

एक पूर्ण उदाहरण के लिए एक-से-एक संबंध मॉडल उदाहरण देखें।

OneToOneField फ़ील्ड्स एक वैकल्पिक parent_link तर्क भी स्वीकार करते हैं।

OneToOneField कक्षाएं एक मॉडल पर स्वचालित रूप से प्राथमिक कुंजी बनने के लिए उपयोग की जाती हैं। यह अब सही नहीं है (हालाँकि आप चाहें तो primary_key दलील में स्वयं ही पास हो सकते हैं)। इस प्रकार, अब एकल मॉडल पर OneToOneField प्रकार के कई क्षेत्रों का होना संभव है।

फाइलों के पार मॉडल

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

from django.db import models
from geography.models import ZipCode

class Restaurant(models.Model):
    # ...
    zip_code = models.ForeignKey(
        ZipCode,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
    )

फ़ील्ड नाम प्रतिबंध

Django मॉडल क्षेत्र के नामों पर केवल दो प्रतिबंध लगाता है:

  1. एक फ़ील्ड नाम पायथन आरक्षित शब्द नहीं हो सकता है, क्योंकि इससे पायथन सिंटैक्स त्रुटि होगी। उदाहरण के लिए:

    class Example(models.Model):
        pass = models.IntegerField() # 'pass' is a reserved word!
    
  2. जिस तरह से Django के क्वेरी लुकअप सिंटैक्स काम करता है, एक फ़ील्ड नाम में एक से अधिक अंडरस्कोर नहीं हो सकता है। उदाहरण के लिए:

    class Example(models.Model):
        foo__bar = models.IntegerField() # 'foo__bar' has two underscores!
    

इन सीमाओं के आसपास काम किया जा सकता है, हालांकि, क्योंकि आपके क्षेत्र का नाम आवश्यक रूप से आपके डेटाबेस कॉलम के नाम से मेल नहीं खाता है। db_column विकल्प देखें।

SQL आरक्षित शब्द, जैसे कि join , where या select , को मॉडल फ़ील्ड नामों के रूप में अनुमति दी जाती है, क्योंकि Django हर अंतर्निहित SQL क्वेरी में सभी डेटाबेस तालिका नामों और स्तंभ नामों से बच जाता है। यह आपके विशेष डेटाबेस इंजन के उद्धरण सिंटैक्स का उपयोग करता है।

कस्टम फ़ील्ड प्रकार

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

Meta विकल्प

अपने मॉडल मेटाडेटा को एक आंतरिक class Meta का उपयोग करके दें, जैसे:

from django.db import models

class Ox(models.Model):
    horn_length = models.IntegerField()

    class Meta:
        ordering = ["horn_length"]
        verbose_name_plural = "oxen"

मॉडल मेटाडेटा "कुछ भी नहीं है जो एक फ़ील्ड है", जैसे कि ऑर्डर करने के विकल्प ( ordering ), डेटाबेस टेबल नाम ( db_table ), या मानव-पठनीय एकवचन और बहुवचन नाम ( verbose_name और verbose_name_plural )। किसी को भी आवश्यकता नहीं है, और मॉडल में class Meta को जोड़ना पूरी तरह से वैकल्पिक है।

सभी संभव Meta विकल्पों की पूरी सूची मॉडल विकल्प संदर्भ में पाई जा सकती है।

मॉडल विशेषताएँ

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

मॉडल के तरीके

अपनी वस्तुओं में कस्टम "पंक्ति-स्तरीय" कार्यक्षमता जोड़ने के लिए एक मॉडल पर कस्टम तरीकों को परिभाषित करें। जबकि Manager विधियों को "टेबल-वाइड" चीजों के लिए करना है, मॉडल विधियों को किसी विशेष मॉडल उदाहरण पर कार्य करना चाहिए।

यह व्यावसायिक तर्क को एक स्थान पर रखने के लिए एक मूल्यवान तकनीक है - मॉडल।

उदाहरण के लिए, इस मॉडल में कुछ कस्टम तरीके हैं:

from django.db import models

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

    def baby_boomer_status(self):
        "Returns the person's baby-boomer status."
        import datetime
        if self.birth_date < datetime.date(1945, 8, 1):
            return "Pre-boomer"
        elif self.birth_date < datetime.date(1965, 1, 1):
            return "Baby boomer"
        else:
            return "Post-boomer"

    @property
    def full_name(self):
        "Returns the person's full name."
        return '%s %s' % (self.first_name, self.last_name)

इस उदाहरण में अंतिम विधि एक property

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

__str__()

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

आप हमेशा इस विधि को परिभाषित करना चाहेंगे; डिफ़ॉल्ट बिल्कुल भी मददगार नहीं है।

get_absolute_url()

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

किसी भी ऑब्जेक्ट में URL है जो विशिष्ट रूप से पहचान करता है उसे इस विधि को परिभाषित करना चाहिए।

पूर्वनिर्धारित मॉडल विधियों को ओवरराइड करना

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

व्यवहार में परिवर्तन के लिए आप इन विधियों (और किसी भी अन्य मॉडल विधि) को ओवरराइड करने के लिए स्वतंत्र हैं।

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

from django.db import models

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

    def save(self, *args, **kwargs):
        do_something()
        super().save(*args, **kwargs)  # Call the "real" save() method.
        do_something_else()

आप बचत करने से भी रोक सकते हैं:

from django.db import models

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

    def save(self, *args, **kwargs):
        if self.name == "Yoko Ono's blog":
            return # Yoko shall never have her own blog!
        else:
            super().save(*args, **kwargs)  # Call the "real" save() method.

सुपरक्लास पद्धति को कॉल करना याद रखना महत्वपूर्ण है - वह super().save(*args, **kwargs) व्यवसाय है - यह सुनिश्चित करने के लिए कि ऑब्जेक्ट अभी भी डेटाबेस में सहेजा गया है। यदि आप सुपरक्लास पद्धति को कॉल करना भूल जाते हैं, तो डिफ़ॉल्ट व्यवहार नहीं होगा और डेटाबेस को छुआ नहीं जाएगा।

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

ओवरराइड किए गए मॉडल तरीकों को थोक संचालन पर नहीं कहा जाता है

ध्यान दें कि किसी ऑब्जेक्ट के लिए delete() विधि को आवश्यक रूप से तब नहीं बुलाया जाता है जब एक क्वेरी के उपयोग से थोक में वस्तुओं को हटा दिया जाता है या cascading delete परिणामस्वरूप। यह सुनिश्चित करने के लिए कि कस्टमाइज्ड डिलीट लॉजिक निष्पादित हो जाए, आप pre_delete और / या post_delete सिग्नल का उपयोग कर सकते हैं।

दुर्भाग्यवश, बल्क में ऑब्जेक्ट्स creating या updating समय कोई वर्कअराउंड नहीं होता है, क्योंकि save() , pre_save , और pre_save से किसी को भी नहीं बुलाया जाता है।

कस्टम SQL को निष्पादित करना

एक अन्य सामान्य पैटर्न मॉडल विधियों और मॉड्यूल-स्तरीय विधियों में कस्टम एसक्यूएल बयान लिख रहा है। कच्चे SQL का उपयोग करने के बारे में अधिक जानकारी के लिए, कच्ची SQL का उपयोग करने पर प्रलेखन देखें।

मॉडल विरासत

Django में मॉडल वंशानुक्रम लगभग समान रूप से काम करता है जिस तरह से पायथन में सामान्य वर्ग विरासत काम करता है, लेकिन पेज की शुरुआत में मूल बातें अभी भी पालन की जानी चाहिए। इसका मतलब है कि बेस क्लास को django.db.models.Model को उप-वर्ग करना चाहिए।

आपको केवल यह निर्णय करना है कि क्या आप चाहते हैं कि माता-पिता मॉडल अपने आप में मॉडल (अपने डेटाबेस तालिकाओं के साथ) हों, या यदि माता-पिता केवल सामान्य जानकारी के धारक हैं जो केवल बाल मॉडल के माध्यम से दिखाई देंगे।

Django में विरासत की तीन शैलियाँ संभव हैं।

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

सार आधार वर्ग

जब आप कुछ सामान्य जानकारी को कई अन्य मॉडलों में डालना चाहते हैं तो सार आधार कक्षाएं उपयोगी होती हैं। आप अपना बेस क्लास लिखते हैं और Meta क्लास में abstract=True करते हैं। यह मॉडल तब किसी भी डेटाबेस तालिका बनाने के लिए उपयोग नहीं किया जाएगा। इसके बजाय, जब इसे अन्य मॉडलों के लिए बेस क्लास के रूप में उपयोग किया जाता है, तो इसके फ़ील्ड को चाइल्ड क्लास के साथ जोड़ा जाएगा।

एक उदाहरण:

from django.db import models

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    class Meta:
        abstract = True

class Student(CommonInfo):
    home_group = models.CharField(max_length=5)

Student मॉडल में तीन फ़ील्ड होंगे: name , age और home_groupCommonInfo मॉडल का उपयोग सामान्य Django मॉडल के रूप में नहीं किया जा सकता है, क्योंकि यह एक सार आधार वर्ग है। यह एक डेटाबेस तालिका उत्पन्न नहीं करता है या एक प्रबंधक है, और इसे तत्काल या सीधे बचाया नहीं जा सकता है।

अमूर्त आधार वर्गों से विरासत में मिले क्षेत्रों को किसी अन्य क्षेत्र या मूल्य के साथ ओवरराइड किया जा सकता है, या None साथ हटाया None जा सकता।

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

Meta इनहेरिटेंस

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

from django.db import models

class CommonInfo(models.Model):
    # ...
    class Meta:
        abstract = True
        ordering = ['name']

class Student(CommonInfo):
    # ...
    class Meta(CommonInfo.Meta):
        db_table = 'student_info'

Django एक आधार वर्ग के Meta वर्ग के लिए एक समायोजन करता है: Meta विशेषता स्थापित करने से पहले, यह abstract=False सेट करता है। इसका मतलब यह है कि अमूर्त आधार वर्ग के बच्चे खुद ही अमूर्त वर्ग नहीं बन जाते हैं। बेशक, आप एक सार आधार वर्ग बना सकते हैं जो एक अन्य सार आधार वर्ग से विरासत में मिला है। आपको हर बार स्पष्ट रूप से abstract=True सेट करने के लिए याद रखने की आवश्यकता है।

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

इस समस्या को हल करने के लिए, जब आप सार बेस क्लास (केवल) में '%(app_label)s' का उपयोग कर रहे हैं, तो मान का हिस्सा '%(app_label)s' और '%(class)s'

  • '%(class)s' को उस चाइल्ड क्लास के निचले-कैसड नाम से बदल दिया जाता है जिसे फील्ड में उपयोग किया जाता है।
  • '%(app_label)s' को उस बच्चे के वर्ग के निचले-नाम के नाम से बदल दिया जाता है जिसे बच्चा वर्ग सम्‍मिलित करता है। प्रत्येक इंस्टॉल किए गए एप्लिकेशन का नाम अद्वितीय होना चाहिए और प्रत्येक ऐप के भीतर मॉडल वर्ग के नाम भी अद्वितीय होने चाहिए, इसलिए परिणामी नाम अलग-अलग हो जाएगा।

उदाहरण के लिए, एक ऐप दिया गया common/models.py :

from django.db import models

class Base(models.Model):
    m2m = models.ManyToManyField(
        OtherModel,
        related_name="%(app_label)s_%(class)s_related",
        related_query_name="%(app_label)s_%(class)ss",
    )

    class Meta:
        abstract = True

class ChildA(Base):
    pass

class ChildB(Base):
    pass

एक अन्य ऐप rare/models.py :

from common.models import Base

class ChildB(Base):
    pass

common.ChildA.m2m का उल्टा नाम। common.ChildA.m2m फील्ड common.ChildA.m2m होगा और रिवर्स क्वेरी का नाम common_childas होगा। सामान्य का उल्टा नाम। common.ChildB.m2m फ़ील्ड common.ChildB.m2m होगा और रिवर्स क्वेरी नाम common_childbs होगा। अंत में, rare.ChildB.m2m का rare.ChildB.m2m नाम। rare.ChildB.m2m फ़ील्ड rare.ChildB.m2m होगा और रिवर्स क्वेरी नाम rare_childbs होगा। यह आपके ऊपर है कि आप अपने संबंधित नाम या संबंधित क्वेरी नाम का निर्माण करने के लिए '%(class)s' और '%(app_label)s' भाग का उपयोग कैसे करते हैं, लेकिन यदि आप इसका उपयोग करना भूल जाते हैं, तो सिस्टम की जाँच करते समय Django त्रुटियों को उठाएगा। (या migrate )।

यदि आप एक सार आधार वर्ग में एक फ़ील्ड के लिए related_name विशेषता निर्दिष्ट नहीं करते हैं, तो डिफ़ॉल्ट रिवर्स नाम '_set' बाद बच्चे वर्ग का नाम होगा, जैसे कि यह सामान्य रूप से होगा यदि आपने सीधे क्षेत्र घोषित किया है बालक वर्ग पर। उदाहरण के लिए, उपरोक्त कोड में, यदि related_name विशेषता को छोड़ दिया गया था, तो childa_set फ़ील्ड के लिए रिवर्स नाम ChildA केस में ChildA और ChildB फ़ील्ड के लिए ChildB

मल्टी-टेबल इनहेरिटेंस

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

from django.db import models

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

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

Place सभी क्षेत्र Restaurant में भी उपलब्ध होंगे, हालांकि डेटा एक अलग डेटाबेस तालिका में निवास करेगा। तो ये दोनों संभव हैं:

>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")

यदि आपके पास Place वह भी एक है Restaurant , तो आप मॉडल नाम के निचले-केस संस्करण का उपयोग करके Place ऑब्जेक्ट से ऑब्जेक्ट पर प्राप्त कर सकते हैं Restaurant :

>>> p = Place.objects.get(id=12)
# If p is a Restaurant object, this will give the child class:
>>> p.restaurant
<Restaurant: ...>

हालांकि, अगर p ऊपर के उदाहरण में था नहीं एक Restaurant (यह सीधे एक के रूप में निर्मित किया गया था Place वस्तु या कुछ अन्य वर्ग के माता पिता था), की चर्चा करते हुए p.restaurant एक उठाएंगे Restaurant.DoesNotExist अपवाद।

उस पर स्वचालित रूप से बनाया OneToOneField गया Restaurant यह Place इस तरह दिखता है:

place_ptr = models.OneToOneField(
    Place, on_delete=models.CASCADE,
    parent_link=True,
)

आप अपनी खुद की घोषणा के द्वारा उस क्षेत्र ओवरराइड कर सकते हैं OneToOneField के साथ parent_link पर Restaurant

Meta और बहु-तालिका विरासत

मल्टी-टेबल इनहेरिटेंस स्थिति में, यह एक बच्चे के वर्ग के लिए अपने माता-पिता के Meta क्लास से विरासत में लेने का कोई मतलब नहीं है । सभी Meta विकल्प पहले से ही मूल वर्ग के लिए लागू किए गए हैं और उन्हें फिर से लागू करने से सामान्य रूप से केवल विरोधाभासी व्यवहार होगा (यह सार आधार वर्ग मामले के विपरीत है, जहां आधार वर्ग अपने आप में मौजूद नहीं है)।

तो एक बाल मॉडल के पास अपने माता-पिता के Meta क्लास तक पहुंच नहीं है । हालांकि, कुछ सीमित मामले हैं जहां बच्चा माता-पिता से व्यवहार विरासत में प्राप्त करता है: यदि बच्चा एक ordering विशेषता या एक get_latest_by विशेषता निर्दिष्ट नहीं करता है , तो यह उसे अपने माता-पिता से विरासत में मिलेगा।

यदि माता-पिता के पास एक आदेश है और आप नहीं चाहते हैं कि बच्चा कोई प्राकृतिक आदेश दे, तो आप इसे स्पष्ट रूप से अक्षम कर सकते हैं:

class ChildModel(ParentModel):
    # ...
    class Meta:
        # Remove parent's ordering effect
        ordering = []

वंशानुक्रम और रिवर्स संबंध

क्योंकि मल्टी-टेबल इनहेरिटेंस OneToOneField बच्चे और माता-पिता को जोड़ने के लिए एक निहित का उपयोग करता है , इसलिए उपरोक्त उदाहरण में माता-पिता से बच्चे को नीचे ले जाना संभव है। हालाँकि, यह उस नाम का उपयोग करता है जो संबंधों और संबंधों के related_name लिए डिफ़ॉल्ट मूल्य है । यदि आप उन प्रकार के संबंधों को मूल मॉडल के उपवर्ग पर रख रहे हैं, तो आपको प्रत्येक ऐसे फ़ील्ड पर विशेषता निर्दिष्ट करनी होगी । यदि आप भूल जाते हैं, तो Django एक सत्यापन त्रुटि बढ़ाएगा। ForeignKey ManyToManyField related_name

उदाहरण के लिए, उपरोक्त Place वर्ग का फिर से उपयोग करते हुए , चलिए एक और उपवर्ग बनाते हैं ManyToManyField :

class Supplier(Place):
    customers = models.ManyToManyField(Place)

इसके परिणामस्वरूप त्रुटि होती है:

Reverse query name for 'Supplier.customers' clashes with reverse query
name for 'Supplier.place_ptr'.

HINT: Add or change a related_name argument to the definition for
'Supplier.customers' or 'Supplier.place_ptr'.

जोड़ने related_name के लिए customers क्षेत्र के रूप में त्रुटि को हल होगा इस प्रकार है: models.ManyToManyField(Place, related_name='provider')

प्रॉक्सी मॉडल

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

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

प्रॉक्सी मॉडल सामान्य मॉडल की तरह घोषित किए जाते हैं। आप Django को बताते हैं कि यह वर्ग की proxy विशेषता सेट करके एक प्रॉक्सी मॉडल है । Meta True

उदाहरण के लिए, मान लें कि आप Person मॉडल में कोई विधि जोड़ना चाहते हैं । आप इसे इस तरह से कर सकते हैं:

from django.db import models

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

class MyPerson(Person):
    class Meta:
        proxy = True

    def do_something(self):
        # ...
        pass

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

>>> p = Person.objects.create(first_name="foobar")
>>> MyPerson.objects.get(first_name="foobar")
<MyPerson: foobar>

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

class OrderedPerson(Person):
    class Meta:
        ordering = ["last_name"]
        proxy = True

अब सामान्य Person प्रश्नों को अनियंत्रित किया जाएगा और OrderedPerson प्रश्नों का आदेश दिया जाएगा last_name

प्रॉक्सी मॉडल नियमित मॉडल की तरह ही Meta विशेषताओं को प्राप्त करते हैं

QuerySet अभी भी उस मॉडल को लौटाएं जो अनुरोध किया गया था

MyPerson जब भी आप ऑब्जेक्ट्स के लिए क्वेरी करते हैं, तो Django वापसी का कोई तरीका नहीं है PersonPerson वस्तुओं के लिए एक क्वेरी उन प्रकार की वस्तुओं को वापस करेगी। प्रॉक्सी ऑब्जेक्ट्स का पूरा बिंदु यह है कि मूल पर निर्भर कोड Person उन का उपयोग करेगा और आपका अपना कोड आपके द्वारा शामिल एक्सटेंशन का उपयोग कर सकता है (जो कि कोई अन्य कोड किसी भी तरह से भरोसा नहीं कर रहा है)। यह Person हर जगह अपनी खुद की रचना के साथ (या किसी अन्य) मॉडल को बदलने का एक तरीका नहीं है ।

आधार वर्ग प्रतिबंध

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

प्रॉक्सी मॉडल मैनेजर

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

ऊपर से हमारे उदाहरण को जारी रखते हुए, आप Person इस तरह से मॉडल को क्वेरी करते समय उपयोग किए गए डिफ़ॉल्ट प्रबंधक को बदल सकते हैं :

from django.db import models

class NewManager(models.Manager):
    # ...
    pass

class MyPerson(Person):
    objects = NewManager()

    class Meta:
        proxy = True

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

# Create an abstract class for the new manager.
class ExtraManagers(models.Model):
    secondary = NewManager()

    class Meta:
        abstract = True

class MyPerson(Person, ExtraManagers):
    class Meta:
        proxy = True

आपको शायद ऐसा करने की आवश्यकता नहीं होगी, लेकिन, जब आप ऐसा करेंगे, यह संभव है।

प्रॉक्सी वंशानुक्रम और अप्रबंधित मॉडल के बीच अंतर

प्रॉक्सी मॉडल इनहेरिटेंस managed एक मॉडल के Meta वर्ग पर विशेषता का उपयोग करते हुए, एक अप्रबंधित मॉडल बनाने के लिए काफी समान लग सकता है ।

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

दूसरी ओर, प्रॉक्सी मॉडल का उद्देश्य बिल्कुल उस मॉडल की तरह व्यवहार करना है, जिसके लिए वे निकटस्थ हैं। वे मूल मॉडल के साथ हमेशा तालमेल बिठाते हैं क्योंकि वे सीधे अपने क्षेत्र और प्रबंधकों को विरासत में देते हैं।

सामान्य नियम हैं:

  1. यदि आप किसी मौजूदा मॉडल या डेटाबेस तालिका को मिरर कर रहे हैं और सभी मूल डेटाबेस तालिका कॉलम नहीं चाहते हैं, तो उपयोग करें Meta.managed=False । यह विकल्प सामान्य रूप से डेटाबेस के विचारों और तालिकाओं के लिए उपयोगी है जो कि Django के नियंत्रण में नहीं है।
  2. यदि आप एक मॉडल के पायथन-ओनली व्यवहार को बदलना चाहते हैं, लेकिन सभी फ़ील्ड को मूल, उपयोग के समान रखें Meta.proxy=True । यह चीजों को सेट करता है ताकि डेटा सहेजे जाने पर प्रॉक्सी मॉडल मूल मॉडल की भंडारण संरचना की एक सटीक प्रतिलिपि हो।

एकाधिक वंशानुक्रम

जैसे पायथन के उपवर्ग के साथ, यह एक Django मॉडल के लिए कई मूल मॉडल से विरासत में संभव है। ध्यान रखें कि सामान्य पायथन नाम संकल्प नियम लागू होते हैं। पहला आधार वर्ग जो एक विशेष नाम (जैसे Meta ) प्रकट होता है, वह प्रयोग किया जाता है; उदाहरण के लिए, इसका मतलब है कि यदि कई माता-पिता Meta क्लास में शामिल हैं, तो केवल पहले एक का उपयोग किया जाएगा, और अन्य सभी को अनदेखा किया जाएगा।

आमतौर पर, आपको कई अभिभावकों से विरासत में मिलने की जरूरत नहीं होगी। मुख्य उपयोग-केस जहां यह उपयोगी है, "मिक्स-इन" कक्षाओं के लिए है: हर वर्ग के लिए एक विशेष अतिरिक्त क्षेत्र या पद्धति को जोड़ना जो मिक्स-इन विरासत में मिला है। अपने वंशानुगत पदानुक्रमों को यथासंभव सरल और सीधा रखने की कोशिश करें ताकि आपको यह पता लगाने के लिए संघर्ष न करना पड़े कि एक विशेष जानकारी कहाँ से आ रही है।

ध्यान दें कि एक सामान्य id प्राथमिक कुंजी फ़ील्ड वाले कई मॉडलों से विरासत में त्रुटि सामने आएगी। एकाधिक वंशानुक्रम का ठीक से उपयोग करने के लिए, आप AutoField आधार मॉडल में एक स्पष्ट का उपयोग कर सकते हैं :

class Article(models.Model):
    article_id = models.AutoField(primary_key=True)
    ...

class Book(models.Model):
    book_id = models.AutoField(primary_key=True)
    ...

class BookReview(Book, Article):
    pass

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

class Piece(models.Model):
    pass

class Article(Piece):
    article_piece = models.OneToOneField(Piece, on_delete=models.CASCADE, parent_link=True)
    ...

class Book(Piece):
    book_piece = models.OneToOneField(Piece, on_delete=models.CASCADE, parent_link=True)
    ...

class BookReview(Book, Article):
    pass

फ़ील्ड नाम "छिपाना" की अनुमति नहीं है

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

यह प्रतिबंध अमूर्त मॉडल से विरासत में प्राप्त मॉडल क्षेत्रों पर लागू नहीं होता है। ऐसे फ़ील्ड को किसी अन्य फ़ील्ड या मान के साथ ओवरराइड किया जा सकता है, या सेटिंग द्वारा हटाया जा सकता है field_name = None

चेतावनी

मॉडल प्रबंधकों को मूल आधार वर्गों से विरासत में मिला है। विरासत में मिले क्षेत्र को ओवरराइड करने से जो विरासत में मिला Manager है, सूक्ष्म कीड़े पैदा कर सकता है। कस्टम प्रबंधक और मॉडल वंशानुक्रम देखें ।

ध्यान दें

कुछ क्षेत्रों मॉडल पर अतिरिक्त विशेषताएं निर्धारित है, जैसे एक ForeignKey साथ एक अतिरिक्त विशेषता को परिभाषित करता है _id के रूप में फ़ील्ड नाम के साथ जोड़ दिया है, साथ ही related_name और related_query_name विदेशी मॉडल पर।

इन अतिरिक्त विशेषताओं को तब तक ओवरराइड नहीं किया जा सकता जब तक कि इसे परिभाषित करने वाले क्षेत्र को परिवर्तित या हटा नहीं दिया जाता है ताकि यह अतिरिक्त विशेषता को परिभाषित न करे।

एक मूल मॉडल में खेतों को ओवरराइड करने से नए उदाहरणों को निर्दिष्ट करने (किस क्षेत्र को प्रारंभिक रूप से परिभाषित किया जा रहा है Model.__init__ ) और क्रमांकन जैसे क्षेत्रों में कठिनाइयों का कारण बनता है । ये ऐसी विशेषताएं हैं जो सामान्य पायथन वर्ग की विरासत से काफी हद तक निपटने की नहीं हैं, इसलिए Django मॉडल वंशानुक्रम और पायथन वर्ग विरासत के बीच का अंतर मनमाना नहीं है।

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

FieldError यदि आप किसी भी पूर्वज मॉडल में किसी मॉडल फ़ील्ड को ओवरराइड करते हैं तो Django उठाएंगे ।

एक पैकेज में मॉडल का आयोजन

manage.py startapp आदेश एक आवेदन संरचना है कि एक भी शामिल है बनाता है models.py फ़ाइल। यदि आपके पास कई मॉडल हैं, तो उन्हें अलग-अलग फ़ाइलों में व्यवस्थित करना उपयोगी हो सकता है।

ऐसा करने के लिए, एक models पैकेज बनाएं । अपने मॉडल को संग्रहीत करने के लिए फ़ाइल और फ़ाइलों के साथ models.py एक myapp/models/ निर्देशिका निकालें और बनाएं __init__.py । आपको __init__.py फ़ाइल में मॉडल आयात करना होगा ।

उदाहरण के लिए, आप था organic.py और synthetic.py में models निर्देशिका:

from .organic import Person
from .synthetic import Robot

स्पष्ट रूप से प्रत्येक मॉडल का उपयोग करने के बजाय from .models import * नाम स्थान को अव्यवस्थित नहीं करने, कोड को अधिक पठनीय बनाने और कोड विश्लेषण टूल को उपयोगी रखने के फायदे हैं।

यह भी देखें

मॉडल संदर्भ
मॉडल फ़ील्ड, संबंधित वस्तुओं और सहित सभी मॉडल से संबंधित एपीआई को शामिल करता है QuerySet

Original text