Django सामग्री प्रकार वास्तव में कैसे काम करते हैं?


148

मैं वास्तव में एक कठिन समय Django की सामग्री प्रकार की अवधारणा लोभी कर रहा हूँ। यह बहुत हैकिश लगता है और आखिरकार, पायथन चीजों को करने के लिए कैसे जाता है। कहा जा रहा है कि, अगर मैं Django का उपयोग करने जा रहा हूं तो मुझे रूपरेखा के दायरे में काम करना होगा।

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


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

1
ठीक है, इसलिए जहां मुझे फंसाया गया, वह यह है कि उन्होंने "TaggedItem" नामक एक वर्ग बनाया, जो मेरे लिए स्पष्ट नहीं था। मुझे यकीन नहीं था कि अगर TaggedItem एक प्लेसहोल्डर "ब्रिज" क्लास था। मेरा प्राकृतिक झुकाव "टर्म" नाम की संपत्ति के साथ "टैग" जैसा कुछ होता।
क्रिस शेल्टन

जवाबों:


307

तो आप अपने काम के कंटेंट टाइप ढांचे का उपयोग करना चाहते हैं?

अपने आप से यह प्रश्न पूछकर शुरू करें: "क्या इनमें से किसी भी मॉडल को उसी तरह से अन्य मॉडलों से संबंधित होने की आवश्यकता है और / या क्या मैं बाद में सड़क पर नीचे इन अप्रत्याशित तरीकों से इन रिश्तों का पुन: उपयोग कर रहा हूं?" हम यह सवाल क्यों पूछते हैं इसका कारण यह है कि सामग्री प्रकार फ्रेमवर्क सबसे अच्छा है: यह मॉडल के बीच सामान्य संबंध बनाता है। ब्ला ब्ला, चलो कुछ कोड में गोता लगाएँ और देखें कि मेरा क्या मतलब है।

# ourapp.models
from django.conf import settings
from django.db import models

# Assign the User model in case it has been "swapped"
User = settings.AUTH_USER_MODEL

# Create your models here
class Post(models.Model):
  author = models.ForeignKey(User)
  title = models.CharField(max_length=75)
  slug = models.SlugField(unique=True)
  body = models.TextField(blank=True)

class Picture(models.Model):
  author = models.ForeignKey(User)
  image = models.ImageField()
  caption = models.TextField(blank=True)

class Comment(models.Model):
  author = models.ForeignKey(User)
  body = models.TextField(blank=True)
  post = models.ForeignKey(Post)
  picture = models.ForeignKey(Picture)

ठीक है, इसलिए हमारे पास सैद्धांतिक रूप से इस रिश्ते को बनाने का एक तरीका है। हालाँकि, पायथन प्रोग्रामर के रूप में, आपकी बेहतर बुद्धि आपको यह बताती है कि आप इसे बेहतर तरीके से चूस सकते हैं। दो ताली!

सामग्री प्रकार फ़्रेमवर्क दर्ज करें!

खैर, अब हम अपने मॉडल पर बारीकी से नज़र रखने जा रहे हैं और उन्हें अधिक "पुन: प्रयोज्य" और सहज होने के लिए फिर से काम कर रहे हैं। आइए अपने Commentमॉडल पर दो विदेशी कुंजियों से छुटकारा पाने के बाद शुरू करें और उन्हें एक के साथ बदलें GenericForeignKey

# ourapp.models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

...

class Comment(models.Model):
  author = models.ForeignKey(User)
  body = models.TextField(blank=True)
  content_type = models.ForeignKey(ContentType)
  object_id = models.PositiveIntegerField()
  content_object = GenericForeignKey()

तो क्या हुआ? खैर, हम अन्य मॉडलों के लिए एक सामान्य संबंध के लिए अनुमति देने के लिए आवश्यक कोड जोड़ते हैं। सूचना कैसे वहाँ सिर्फ एक से अधिक है GenericForeignKey, लेकिन यह भी एक ForeignKeyके लिए ContentTypeऔर एक PositiveIntegerFieldके लिए object_id। ये क्षेत्र Django को यह बताने के लिए हैं कि यह किस प्रकार की वस्तु से संबंधित है और उस वस्तु के लिए आईडी क्या है। वास्तव में, यह समझ में आता है क्योंकि Django को इन संबंधित वस्तुओं को देखने के लिए दोनों की आवश्यकता होगी।

खैर, यह बहुत अजगर की तरह नहीं है ... इसके थोड़े बदसूरत!

आप शायद एयर-टाइट, स्पॉटलेस, सहज कोड की तलाश कर रहे हैं जो गुइडो वैन रॉसुम को गर्वित करेगा। मैं तुम्हें ले आता हूं। आइए GenericRelationमैदान देखें ताकि हम इस पर एक सुंदर धनुष डाल सकें।

# ourapp.models
from django.contrib.contenttypes.fields import GenericRelation

...

class Post(models.Model):
  author = models.ForeignKey(User)
  title = models.CharField(max_length=75)
  slug = models.SlugField(unique=True)
  body = models.TextField(blank=True)
  comments = GenericRelation('Comment')

class Picture(models.Model):
  author = models.ForeignKey(User)
  image = models.ImageField()
  caption = models.TextField(blank=True)
  comments = GenericRelation('Comment')

बैम! ऐसे ही आप इन दो मॉडलों के लिए टिप्पणियों के साथ काम कर सकते हैं। वास्तव में, चलो आगे बढ़ते हैं और हमारे शेल में करते हैं ( python manage.py shellआपके Django प्रोजेक्ट निर्देशिका से प्रकार )।

>>> from django.contrib.auth import get_user_model
>>> from ourapp.models import Picture, Post

# We use get_user_model() since we are referencing directly
User = get_user_model()

# Grab our own User object
>>> me = User.objects.get(username='myusername')

# Grab the first of our own pictures so we can comment on it
>>> pic = Picture.objects.get(author=me)

# Let's start making a comment for our own picture
>>> pic.comments.create(author=me, body="Man, I'm cool!")

# Let's go ahead and retrieve the comments for this picture now
>>> pic.comments.all()
[<Comment: "Man, I'm cool!">]

# Same for Post comments
>>> post = Post.objects.get(author=me)
>>> post.comments.create(author=me, body="So easy to comment now!")
>>> post.comments.all()
[<Comment: "So easy to comment now!"]

यह इत्ना आसान है।

इन "सामान्य" संबंधों के अन्य व्यावहारिक निहितार्थ क्या हैं?

सामान्य विदेशी कुंजियाँ विभिन्न अनुप्रयोगों के बीच कम घुसपैठ संबंधों की अनुमति देती हैं। उदाहरण के लिए, मान लें कि हमने टिप्पणी मॉडल को खींच लिया है जिसका नाम स्वयं का ऐप है chatterly। अब हम नाम से एक और एप्लीकेशन बनाना चाहते हैंnoise_nimbus लोग अपने संगीत को दूसरों के साथ साझा करने के लिए रखते हैं।

क्या होगा अगर हम उन गानों में कमेंट्स जोड़ना चाहते हैं? ठीक है, हम सिर्फ एक सामान्य संबंध बना सकते हैं:

# noise_nimbus.models
from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation
from django.db import models

from chatterly.models import Comment

# For a third time, we take the time to ensure custom Auth isn't overlooked
User = settings.AUTH_USER_MODEL

# Create your models here
class Song(models.Model):
  '''
  A song which can be commented on.
  '''
  file = models.FileField()
  author = models.ForeignKey(User)
  title = models.CharField(max_length=75)
  slug = models.SlugField(unique=True)
  description = models.TextField(blank=True)
  comments = GenericRelation(Comment)

मुझे आशा है कि आप लोगों को यह मददगार लगा होगा क्योंकि मुझे ऐसा कुछ पसंद आया होगा जिसने मुझे GenericForeignKeyऔर GenericRelationक्षेत्रों का अधिक यथार्थवादी अनुप्रयोग दिखाया ।

क्या यह सच होना अच्छा है?

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

मेरे द्वारा यहां प्रदर्शित की गई सामग्री प्रकार की रूपरेखा से अधिक है। ग्रैन्युलैरिटी और अधिक वर्बोज़ उपयोग का एक संपूर्ण स्तर है, लेकिन औसत व्यक्ति के लिए, यह है कि आप मेरी राय में 10 में से 9 बार इसका उपयोग कैसे करेंगे।

सामान्य संबंधक (!) सावधान!

इसके बजाय एक बड़ी चेतावनी यह है कि जब आप एक का उपयोग करते हैं GenericRelation, यदि जिस मॉडल पर GenericRelationलागू ( Picture) हटा दिया गया है, सभी संबंधित ( Comment) ऑब्जेक्ट भी हटा दिए जाएंगे। या कम से कम इस लेखन के समय के रूप में।


11
तो अगर मैं उपयोग GenericRelationमें Postऔर Pictureफिर मैं उपयोग की जरूरत नहीं है object_id, content_typeऔर content_objectमें Comment?
एवी

5
यह अच्छा होगा कि आधिकारिक Django दस्तावेज़ीकरण में कहीं-कहीं कंटेंटाइप फ्रेमवर्क का इतना अच्छा विवरण हो। मेरे लिए जैसा कि मैंने महसूस किया कि इस बंदरगाह को पढ़ने के बाद ही यह रूपरेखा क्या करती है। धन्यवाद।
प्रॉक्टर

2
थोड़ा देर से ... लेकिन मैंने सुना है कि सामग्री प्रकार के ढांचे का उपयोग करते हुए, आपका एप्लिकेशन ठीक से माप नहीं सकता है। क्या कोई मुझे बता सकता है कि क्या यह सच है या एक धोखा है?
करण कुमार 5

1
प्रोग्रामिंग में सब कुछ के साथ, करण, जवाब हमेशा "यह निर्भर करता है।" मैं कहूंगा कि सामग्री प्रकारों का उपयोग करें। यह टेबल ओरिएंटेड एसक्यूएल सिस्टम के कुछ कठोर फंडामेंटल को बायपास करने का एक "समझौता" है। समय से पहले अपने ऐप का अनुकूलन न करें! Django अपने रास्ते से बाहर निकलने में सबसे अच्छा है ताकि आप अगली पीढ़ी के एप्लिकेशन को लिख सकें जो आप हमेशा से चाहते थे: इसका उपयोग अपने लाभ के लिए करें!
क्रिस शेल्टन ने

2
करण, इसमें कुछ सच्चाई है। मैं एक ऐसे एप्लिकेशन पर काम कर रहा हूं जो उपयोगकर्ताओं के लिए सूचनाओं को ट्रैक करता है। प्रत्येक सूचना में हमारे द्वारा संग्रहीत किसी अन्य प्रकार की सामग्री के लिए GenericForeignKey संबंध होता है। जब भी कोई उपयोगकर्ता सूचनाएं देखता है, तो ORM सभी संबंधित सामग्री प्राप्त करने के लिए N क्वेरीज़ जारी करता है। शायद ही आदर्श।
ट्रैविस मेहलिंगर

-2

ठीक है आपके प्रश्न का सीधा उत्तर: (django स्रोत कोड से) है: RFC 2616, धारा 3.7 के अनुसार मीडिया प्रकार पार्स करना।

यह कहने का आंसू तरीका है कि यह 'सामग्री-प्रकार' httpd हेडर के साथ - साथ / आप-को-संशोधित / पास करता है / पढ़ता है ।

हालाँकि, आप अधिक अभ्यास उपयोग उदाहरण के लिए पूछ रहे हैं। मेरे पास आपके लिए 2 सुझाव हैं:

1: इस कोड की जाँच करें

def index(request):
   media_type='text/html'
   if request.META.has_key('CONTENT_TYPE'):
      media_type = request.META['CONTENT_TYPE'].split(';')[0]

   if media_type.lower() == 'application/json':
      return HttpResponse("""{ "ResponseCode": "Success"}""", content_type="application/json; charset=UTF-8")

   return HttpResponse("<h1>regular old joe</h1>");

2: याद रखें कि django अजगर है, और जैसे कि यह अजगर समुदाय की शक्ति का उत्पादन करता है। Django के लिए 2 भयानक RESTFul प्लगइन्स हैं। इसलिए यदि आप देखना चाहते हैं कि खरगोश पूरी तरह से कितना गहरा हो जाता है, तो आप देख सकते हैं।

मेरा सुझाव है कि django- रेस्ट-फ्रेमवर्क ट्यूटोरियल के माध्यम से जाना जो विशेष रूप से 'विभिन्न सामग्रियों / प्रकारों पर अभिनय' को संबोधित करेगा। ध्यान दें: कॉन्टेंट-टाइप हेडर का उपयोग rest वर्जन ’रेस्टफुल एपीआई के लिए करना आम बात है ।


1
क्या वह जिसका जिक्र कर रहा है? या सामग्रीटाइप्स
petkostas

1
हाँ, मैं सामग्री प्रकार के ढांचे की बात कर रहा था। हो सकता है कि मैंने खुद को समझाकर अच्छा काम नहीं किया हो। मैं प्रतिक्रिया की परवाह किए बिना सराहना करता हूं। इसके लायक क्या है, अगर यह मेरा सवाल था, तो आपने इसे पार्क से बाहर खटखटाया होगा))
क्रिस शेल्टन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.