Django 2.1 - The contenttypes framework

कंटेंटपाइप फ्रेमवर्क




django

कंटेंटपाइप फ्रेमवर्क

Django में एक contenttypes एप्लिकेशन शामिल है जो आपके Django द्वारा संचालित प्रोजेक्ट में स्थापित सभी मॉडलों को ट्रैक कर सकता है, आपके मॉडल के साथ काम करने के लिए एक उच्च-स्तरीय, सामान्य इंटरफ़ेस प्रदान करता है।

अवलोकन

django.contrib.contenttypes.models.ContentType एप्लिकेशन के केंद्र में ContentType मॉडल है, जो django.contrib.contenttypes.models.ContentType पर django.contrib.contenttypes.models.ContentType ContentType उदाहरण आपके प्रोजेक्ट में स्थापित मॉडल के बारे में जानकारी का प्रतिनिधित्व करते हैं और संग्रहीत करते हैं, और जब भी नए मॉडल इंस्टॉल किए जाते हैं, तब ContentType नए इंस्टेंस स्वचालित रूप से बनाए जाते हैं।

ContentType उदाहरणों में उन मॉडल से ऑब्जेक्ट को क्वेरी करने के लिए और उनके मॉडल मॉडल वर्गों को वापस करने के तरीके हैं। ContentType में एक कस्टम मैनेजर भी है जो ContentType साथ काम करने के लिए और किसी विशेष मॉडल के लिए ContentType इंस्टेंस प्राप्त करने के लिए तरीके जोड़ता है।

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

Contenttypes ढांचे को स्थापित करना

सामग्री की रूपरेखा को django-admin startproject द्वारा बनाई गई डिफ़ॉल्ट INSTALLED_APPS सूची में शामिल किया गया है, लेकिन यदि आपने इसे हटा दिया है या यदि आपने मैन्युअल रूप से अपनी INSTALLED_APPS सूची सेट की है, तो आप अपने INSTALLED_APPS 'django.contrib.contenttypes' जोड़कर इसे सक्षम कर सकते हैं। सेटिंग।

यह आमतौर पर एक अच्छा विचार है कि contenttypes फ्रेमवर्क स्थापित किया गया है; Django के अन्य बंडल किए गए अनुप्रयोगों में से कई को इसकी आवश्यकता है:

  • व्यवस्थापक एप्लिकेशन इसका उपयोग व्यवस्थापक इंटरफ़ेस के माध्यम से जोड़े गए या बदले गए प्रत्येक ऑब्जेक्ट के इतिहास को लॉग करने के लिए करता है।
  • Django के authentication framework का उपयोग उपयोगकर्ता अनुमतियों को विशिष्ट मॉडल से जोड़ने के लिए करता है।

ContentType मॉडल

class ContentType

ContentType प्रत्येक उदाहरण में दो फ़ील्ड होते हैं, जिन्हें एक साथ लिया जाता है, विशिष्ट रूप से एक स्थापित मॉडल का वर्णन करता है:

app_label

मॉडल का उपयोग करने वाले एप्लिकेशन का नाम है। यह मॉडल के app_label विशेषता से लिया गया है, और इसमें एप्लिकेशन के पायथन आयात पथ का केवल अंतिम भाग शामिल है; उदाहरण के लिए, app_label , contenttypes का एक app_label बन जाता है।

model

मॉडल वर्ग का नाम।

इसके अतिरिक्त, निम्नलिखित संपत्ति उपलब्ध है:

name

सामग्री प्रकार का मानव-पठनीय नाम। यह मॉडल की verbose_name विशेषता से लिया गया है।

आइए एक उदाहरण देखें कि यह कैसे काम करता है। यदि आपके पास पहले से ही contenttypes एप्लिकेशन इंस्टॉल है, और फिर अपनी INSTALLED_APPS सेटिंग the sites application को जोड़ें और इसे इंस्टॉल manage.py migrate लिए manage.py migrate चलाएं, मॉडल django.contrib.sites.models.Site आपके डेटाबेस में इंस्टॉल हो जाएगा। इसके साथ ही ContentType का एक नया उदाहरण निम्नलिखित मानों के साथ बनाया जाएगा:

  • app_label 'sites' (पायथन पथ django.contrib.sites के अंतिम भाग) पर सेट किया जाएगा।
  • model को 'site' सेट किया जाएगा।

ContentType इंस्टेंस पर विधियाँ

प्रत्येक ContentType आवृत्ति में वे विधियाँ होती हैं जो आपको ContentType उदाहरण से उस मॉडल को प्राप्त करने की अनुमति देती हैं, जो उस का प्रतिनिधित्व करती है, या उस ऑब्जेक्ट से पुनर्प्राप्त करने के लिए:

ContentType.get_object_for_this_type(**kwargs)

जिस मॉडल के ContentType प्रतिनिधित्व करता है, उसके लिए मान्य लुकअप तर्कों का एक सेट लेता है और संबंधित मॉडल को लौटाता है।

ContentType.model_class()

इस ContentType उदाहरण द्वारा प्रस्तुत मॉडल वर्ग लौटाता है।

उदाहरण के लिए, हम User मॉडल के लिए ContentType देख सकते हैं:

>>> from django.contrib.contenttypes.models import ContentType
>>> ContentType.objects.get(app_label="auth", model="user")
<ContentType: user>

और फिर किसी विशेष User लिए क्वेरी करने के लिए, या User मॉडल वर्ग तक पहुँच प्राप्त करने के लिए इसका उपयोग करें:

>>> user_type.model_class()
<class 'django.contrib.auth.models.User'>
>>> user_type.get_object_for_this_type(username='Guido')
<User: Guido>

साथ में, get_object_for_this_type() और model_class() दो अत्यंत महत्वपूर्ण उपयोग मामलों को सक्षम करें:

  1. इन विधियों का उपयोग करते हुए, आप उच्च-स्तरीय जेनेरिक कोड लिख सकते हैं जो किसी भी स्थापित मॉडल पर प्रश्न करता है - एक ही विशिष्ट मॉडल वर्ग को आयात और उपयोग करने के बजाय, आप एक app_label और model को रनटाइम पर एक ContentType लुकअप में पास कर सकते हैं, और फिर उसके साथ काम कर सकते हैं मॉडल वर्ग या वस्तुओं को पुनः प्राप्त करना।
  2. आप किसी अन्य मॉडल को ContentType से संबंधित मॉडल वर्गों के लिए विशेष रूप से बांधने के उदाहरण के रूप में संबंधित कर सकते हैं, और उन मॉडल कक्षाओं तक पहुंच प्राप्त करने के लिए इन विधियों का उपयोग कर सकते हैं।

Django के कई बंडल एप्लिकेशन बाद की तकनीक का उपयोग करते हैं। उदाहरण के लिए, Django के प्रमाणीकरण ढांचे में the permissions system ContentType लिए एक विदेशी कुंजी के साथ एक Permission मॉडल का उपयोग करती है; इससे Permission "ब्लॉग प्रविष्टि जोड़ सकते हैं" या "समाचार कहानी हटा सकते हैं" जैसी अवधारणाओं का प्रतिनिधित्व करती है।

ContentTypeManager

class ContentTypeManager

ContentType में एक कस्टम मैनेजर भी है, ContentTypeManager , जो निम्नलिखित तरीके जोड़ता है:

clear_cache()

उन ContentType का ट्रैक रखने के लिए ContentType द्वारा उपयोग किए जाने वाले आंतरिक कैश को साफ़ करता है जिसके लिए उसने ContentType इंस्टेंस बनाए हैं। आपको शायद कभी इस विधि को स्वयं कॉल करने की आवश्यकता नहीं होगी; जरूरत पड़ने पर Django इसे स्वचालित रूप से कॉल करेगा।

get_for_id(id)

ID द्वारा एक ContentType लुकअप करें। चूंकि यह विधि समान साझा कैश का उपयोग get_for_model() रूप में get_for_model() , इसलिए इस सामग्री को सामान्य ContentType.objects.get(pk=id) से अधिक उपयोग करना पसंद किया जाता है

get_for_model(model, for_concrete_model=True)

या तो एक मॉडल वर्ग या एक मॉडल का एक उदाहरण लेता है, और उस मॉडल का प्रतिनिधित्व करने वाले ContentType उदाहरण देता है। for_concrete_model=False प्रॉक्सी मॉडल के ContentType को लाने की अनुमति देता है।

get_for_models(*models, for_concrete_models=True)

मॉडल कक्षाओं की एक विविध संख्या लेता है, और एक मॉडल की मैपिंग करता है जो मॉडल कक्षाओं को कंटेंट टाइप उदाहरणों का प्रतिनिधित्व करता है। for_concrete_models=False प्रॉक्सी मॉडल के ContentType को लाने की अनुमति देता है।

get_by_natural_key(app_label, model)

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

get_for_model() विधि विशेष रूप से तब उपयोगी होती है जब आप जानते हैं कि आपको ContentType साथ काम करने की आवश्यकता है, लेकिन मैन्युअल लुकअप करने के लिए मॉडल के मेटाडेटा को प्राप्त करने की परेशानी में नहीं जाना चाहते हैं:

>>> from django.contrib.auth.models import User
>>> ContentType.objects.get_for_model(User)
<ContentType: user>

सामान्य संबंध

अपने स्वयं के मॉडल में से एक से एक विदेशी कुंजी को ContentType जोड़ना आपके मॉडल को प्रभावी रूप से खुद को दूसरे मॉडल वर्ग में बाँधने की अनुमति देता है, जैसा कि ऊपर दिए गए Permission मॉडल के उदाहरण में है। लेकिन मॉडल के बीच सही मायने में सामान्य (कभी-कभी "बहुरूपी" कहा जाता है) रिश्तों को सक्षम करने के लिए एक कदम आगे जाना और ContentType का उपयोग करना संभव है।

एक सरल उदाहरण एक टैगिंग सिस्टम है, जो इस तरह दिख सकता है:

from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models

class TaggedItem(models.Model):
    tag = models.SlugField()
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    def __str__(self):
        return self.tag

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

class GenericForeignKey

एक GenericForeignKey स्थापना के लिए तीन भाग हैं:

  1. अपने मॉडल को ContentType ForeignKey लिए एक ForeignKey दें। इस फ़ील्ड का सामान्य नाम "content_type" है।
  2. अपने मॉडल को एक ऐसा क्षेत्र दें, जो आपके द्वारा संबंधित मॉडल से प्राथमिक प्रमुख मूल्यों को संग्रहीत कर सकता है। अधिकांश मॉडलों के लिए, इसका मतलब है एक PositiveIntegerField । इस फ़ील्ड का सामान्य नाम "object_id" है।
  3. अपने मॉडल को एक GenericForeignKey दें, और इसे ऊपर वर्णित दो क्षेत्रों के नाम दें। यदि इन फ़ील्ड्स को "content_type" और "object_id" नाम दिया गया है, तो आप इसे छोड़ सकते हैं - वे डिफ़ॉल्ट फ़ील्ड नाम हैं GenericForeignKey लिए GenericForeignKey दिखेगा।
for_concrete_model

यदि False , तो फ़ील्ड प्रॉक्सी मॉडल को संदर्भित करने में सक्षम होगी। डिफ़ॉल्ट True । यह get_for_model() लिए get_for_model() तर्क को get_for_model()

प्राथमिक कुंजी प्रकार संगतता

संबंधित get_db_prep_value() फ़ील्ड के समान " get_db_prep_value() " फ़ील्ड का प्रकार नहीं होना चाहिए, लेकिन उनके प्राथमिक कुंजी मान उसी प्रकार के लिए समान होना चाहिए जैसे " get_db_prep_value() " फ़ील्ड इसके get_db_prep_value() विधि द्वारा।

उदाहरण के लिए, यदि आप या तो IntegerField या CharField प्राथमिक कुंजी फ़ील्ड के साथ मॉडल के लिए सामान्य संबंधों को अनुमति देना चाहते हैं, तो आप अपने मॉडल पर "object_id" फ़ील्ड के लिए CharField उपयोग कर सकते हैं क्योंकि पूर्णांक__ get_db_prep_value() द्वारा स्ट्रिंग्स के लिए get_db_prep_value() किए जा सकते हैं।

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

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

कन्टैंट ContentType वस्तुओं के संदर्भों को क्रमबद्ध करना

यदि आप डेटा को क्रमबद्ध कर रहे हैं (उदाहरण के लिए, fixtures बनाते समय) तो सामान्य संबंधों को लागू करने वाले मॉडल से, आपको संभवतः संबंधित ContentType ऑब्जेक्ट्स की विशिष्ट पहचान करने के लिए एक प्राकृतिक कुंजी का उपयोग करना चाहिए। अधिक जानकारी के लिए प्राकृतिक कुंजियाँ और dumpdata --natural-foreign देखें।

यह सामान्य ForeignKey लिए उपयोग किए जाने वाले एपीआई के समान एपीआई को सक्षम करेगा; प्रत्येक TaggedItem पास एक content_object फ़ील्ड होगा जो उस वस्तु से संबंधित है, जिसे वह संबंधित है, और आप उस फ़ील्ड को असाइन कर सकते हैं या एक TaggedItem बनाते समय उसका उपयोग कर सकते हैं:

>>> from django.contrib.auth.models import User
>>> guido = User.objects.get(username='Guido')
>>> t = TaggedItem(content_object=guido, tag='bdfl')
>>> t.save()
>>> t.content_object
<User: Guido>

यदि संबंधित ऑब्जेक्ट हटा दिया जाता है, तो content_type और object_id फ़ील्ड उनके मूल मानों पर सेट हो जाते हैं और GenericForeignKey None देता है:

>>> guido.delete()
>>> t.content_object  # returns None

GenericForeignKey को लागू करने के तरीके के कारण, आप डेटाबेस API के माध्यम से filter() और exclude() उदाहरण के लिए) के साथ सीधे ऐसे फ़ील्ड का उपयोग नहीं कर सकते। क्योंकि GenericForeignKey एक सामान्य फ़ील्ड ऑब्जेक्ट नहीं है, ये उदाहरण काम नहीं करेंगे:

# This will fail
>>> TaggedItem.objects.filter(content_object=guido)
# This will also fail
>>> TaggedItem.objects.get(content_object=guido)

इसी तरह, GenericForeignKey में प्रदर्शित नहीं होता है।

सामान्य संबंधों को उलट दें

class GenericRelation
related_query_name

इस ऑब्जेक्ट पर संबंधित ऑब्जेक्ट का संबंध डिफ़ॉल्ट रूप से मौजूद नहीं है। related_query_name सेट करना संबंधित वस्तु से इस पर वापस संबंध बनाता है। यह संबंधित ऑब्जेक्ट से क्वेरी और फ़िल्टरिंग की अनुमति देता है।

यदि आप जानते हैं कि कौन से मॉडल आप सबसे अधिक बार उपयोग कर रहे हैं, तो आप अतिरिक्त API सक्षम करने के लिए "रिवर्स" जेनेरिक संबंध भी जोड़ सकते हैं। उदाहरण के लिए:

from django.contrib.contenttypes.fields import GenericRelation
from django.db import models

class Bookmark(models.Model):
    url = models.URLField()
    tags = GenericRelation(TaggedItem)

Bookmark उदाहरणों में प्रत्येक में एक tags विशेषता होगी, जिसका उपयोग उनके संबंधित TaggedItems को पुनः प्राप्त करने के लिए किया जा सकता है:

>>> b = Bookmark(url='https://www.djangoproject.com/')
>>> b.save()
>>> t1 = TaggedItem(content_object=b, tag='django')
>>> t1.save()
>>> t2 = TaggedItem(content_object=b, tag='python')
>>> t2.save()
>>> b.tags.all()
<QuerySet [<TaggedItem: django>, <TaggedItem: python>]>

GenericRelation को GenericRelation सेट के साथ परिभाषित करने से संबंधित ऑब्जेक्ट से क्वेरी करने की अनुमति मिलती है:

tags = GenericRelation(TaggedItem, related_query_name='bookmarks')

यह TaggedItem से Bookmark पर फ़िल्टर करने, ऑर्डर करने और अन्य क्वेरी संचालन को TaggedItem :

>>> # Get all tags belonging to bookmarks containing `django` in the url
>>> TaggedItem.objects.filter(bookmarks__url__contains='django')
<QuerySet [<TaggedItem: django>, <TaggedItem: python>]>

बेशक, यदि आप रिवर्स रिलेशनशिप नहीं जोड़ते हैं, तो आप उसी प्रकार के लुकअप को मैन्युअल रूप से कर सकते हैं:

>>> b = Bookmark.objects.get(url='https://www.djangoproject.com/')
>>> bookmark_type = ContentType.objects.get_for_model(b)
>>> TaggedItem.objects.filter(content_type__pk=bookmark_type.id, object_id=b.id)
<QuerySet [<TaggedItem: django>, <TaggedItem: python>]>

जैसे GenericForeignKey रूप में सामग्री-प्रकार और ऑब्जेक्ट-आईडी फ़ील्ड के नामों को स्वीकार करता है, वैसे ही GenericRelation भी करता है; यदि जिस मॉडल में जेनेरिक विदेशी कुंजी है, उन क्षेत्रों के लिए गैर-डिफ़ॉल्ट नामों का उपयोग कर रहा है, तो आपको GenericRelation सेट करते समय फ़ील्ड के नामों को पास करना होगा। उदाहरण के लिए, अगर TaggedItem मॉडल ने अपनी जेनेरिक विदेशी कुंजी बनाने के लिए content_type_fk और object_primary_key नामक उपरोक्त उपयोग किए गए फ़ील्ड का उल्लेख किया है, तो एक जेनेरिक GenericRelation को इस तरह परिभाषित करने की आवश्यकता होगी:

tags = GenericRelation(
    TaggedItem,
    content_type_field='content_type_fk',
    object_id_field='object_primary_key',
)

यह भी ध्यान दें, कि यदि आप GenericRelation ऑब्जेक्ट को GenericRelation , तो जिन ऑब्जेक्ट्स पर GenericForeignKey इंगित होता है, उन्हें भी हटा दिया जाएगा। ऊपर दिए गए उदाहरण में, इसका मतलब है कि यदि कोई Bookmark ऑब्जेक्ट हटा दिया गया है, तो कोई भी इंगित करने वाली ऑब्जेक्टइमेट्स ऑब्जेक्ट उसी समय हटा दिया जाएगा।

ForeignKey विपरीत, GenericForeignKey इस व्यवहार को अनुकूलित करने के लिए on_delete तर्क को स्वीकार नहीं करता है; यदि वांछित है, तो आप GenericRelation का उपयोग न करके केवल कैस्केड-विलोपन से बच सकते हैं, और वैकल्पिक व्यवहार को pre_delete सिग्नल के माध्यम से प्रदान किया जा सकता है।

सामान्य संबंध और एकत्रीकरण

Django का डेटाबेस एग्रीगेशन एपीआई एक GenericRelation साथ काम करता है। उदाहरण के लिए, आप यह जान सकते हैं कि सभी बुकमार्क में कितने टैग हैं:

>>> Bookmark.objects.aggregate(Count('tags'))
{'tags__count': 3}

रूपों में सामान्य संबंध

django.contrib.contenttypes.forms मॉड्यूल प्रदान करता है:

class BaseGenericInlineFormSet
generic_inlineformset_factory(model, form=ModelForm, formset=BaseGenericInlineFormSet, ct_field="content_type", fk_field="object_id", fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, validate_max=False, for_concrete_model=True, min_num=None, validate_min=False)

modelformset_factory() का उपयोग करके एक modelformset_factory() लौटाता है।

यदि आप क्रमशः चूक, content_type और object_id से अलग हैं, तो आपको ct_field और fk_field प्रदान करना होगा। अन्य पैरामीटर modelformset_factory() और inlineformset_factory() modelformset_factory() में प्रलेखित के समान हैं।

for_concrete_model तर्क for_concrete_model तर्क से मेल GenericForeignKey

सामान्य संबंध सामान्य में

django.contrib.contenttypes.admin मॉड्यूल GenericTabularInline और GenericTabularInline ( GenericTabularInline उपवर्ग) प्रदान करता है

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

class GenericInlineModelAdmin

InlineModelAdmin वर्ग एक InlineModelAdmin वर्ग से सभी गुण प्राप्त करता है। हालांकि, यह सामान्य संबंध के साथ काम करने के लिए अपने स्वयं के जोड़े को जोड़ता है:

ct_field

मॉडल पर ContentType विदेशी कुंजी फ़ील्ड का नाम। Content_type में डिफ़ॉल्ट।

ct_fk_field

पूर्णांक फ़ील्ड का नाम जो संबंधित ऑब्जेक्ट की आईडी का प्रतिनिधित्व करता है। Object_id के लिए डिफ़ॉल्ट।

class GenericTabularInline
class GenericStackedInline

क्रमशः खड़ी और सारणीबद्ध लेआउट के साथ GenericInlineModelAdmin उपवर्ग।