2009-05-31 24 views
37

मैं एक संदेश प्रणाली बनाने की कोशिश कर रहा हूं जहां एक संदेश प्रेषक और प्राप्तकर्ता सामान्य संस्थाएं हो सकते हैं। यह प्रेषक के लिए ठीक लगता है, जहां संदर्भ के लिए केवल ऑब्जेक्ट है (GenericForeignKey) लेकिन मैं यह नहीं समझ सकता कि प्राप्तकर्ताओं के लिए इस बारे में कैसे जाना है (जेनेरिकमैनी टोमनीकी ??)जेनेरिक कई से कई रिश्ते

नीचे एक सरल उदाहरण है। PersonClient और CompanyClient क्लाइंट से गुण प्राप्त करता है लेकिन उनके स्वयं के विशिष्ट विवरण होते हैं। आखिरी पंक्ति चिपकने वाला बिंदु है। कैसे आप संदेश प्राप्तकर्ताओं, CompanyClients और PersonClients

class Client(models.Model): 
     city = models.CharField(max_length=16) 

     class Meta: 
      abstract = True 

    class PersonClient(Client): 
     first_name = models.CharField(max_length=16) 
     last_name = models.CharField(max_length=16) 
     gender = models.CharField(max_length=1) 

    class CompanyClient(Client): 
     name = models.CharField(max_length=32) 
     tax_no = PositiveIntegerField() 

    class Message(models.Model): 
     msg_body = models.CharField(max_length=1024) 
     sender = models.ForeignKey(ContentType) 
     recipients = models.ManyToManyField(ContentType) 

उत्तर

50

आप मैन्युअल रूप से संदेश और प्राप्तकर्ता के बीच जंक्शन तालिका बनाने के द्वारा इस सामान्य संबंधों का उपयोग कर लागू कर सकते हैं:

from django.db import models 
from django.contrib.contenttypes import generic 
from django.contrib.contenttypes.models import ContentType 

class Client(models.Model): 
    city = models.CharField(max_length=16) 

    # These aren't required, but they'll allow you do cool stuff 
    # like "person.sent_messages.all()" to get all messages sent 
    # by that person, and "person.received_messages.all()" to 
    # get all messages sent to that person. 
    # Well...sort of, since "received_messages.all()" will return 
    # a queryset of "MessageRecipient" instances. 
    sent_messages = generic.GenericRelation('Message', 
     content_type_field='sender_content_type', 
     object_id_field='sender_id' 
    ) 
    received_messages = generic.GenericRelation('MessageRecipient', 
     content_type_field='recipient_content_type', 
     object_id_field='recipient_id' 
    ) 

    class Meta: 
     abstract = True 

class PersonClient(Client): 
    first_name = models.CharField(max_length=16) 
    last_name = models.CharField(max_length=16) 
    gender = models.CharField(max_length=1) 

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

class CompanyClient(Client): 
    name = models.CharField(max_length=32) 
    tax_no = models.PositiveIntegerField() 

    def __unicode__(self): 
     return self.name 

class Message(models.Model): 
    sender_content_type = models.ForeignKey(ContentType) 
    sender_id = models.PositiveIntegerField() 
    sender = generic.GenericForeignKey('sender_content_type', 'sender_id') 
    msg_body = models.CharField(max_length=1024) 

    def __unicode__(self): 
     return u'%s...' % self.msg_body[:25] 

class MessageRecipient(models.Model): 
    message = models.ForeignKey(Message) 
    recipient_content_type = models.ForeignKey(ContentType) 
    recipient_id = models.PositiveIntegerField() 
    recipient = generic.GenericForeignKey('recipient_content_type', 'recipient_id') 

    def __unicode__(self): 
     return u'%s sent to %s' % (self.message, self.recipient) 

तुम इतनी तरह से ऊपर के मॉडल का उपयोग करेंगे:

>>> person1 = PersonClient.objects.create(first_name='Person', last_name='One', gender='M') 
>>> person2 = PersonClient.objects.create(first_name='Person', last_name='Two', gender='F') 
>>> company = CompanyClient.objects.create(name='FastCompany', tax_no='4220') 
>>> company_ct = ContentType.objects.get_for_model(CompanyClient) 
>>> person_ct = ContentType.objects.get_for_model(person1) # works for instances too. 

# now we create a message: 

>>> msg = Message.objects.create(sender_content_type=person_ct, sender_id=person1.pk, msg_body='Hey, did any of you move my cheese?') 

# and send it to a coupla recipients: 

>>> MessageRecipient.objects.create(message=msg, recipient_content_type=person_ct, recipient_id=person2.pk) 
>>> MessageRecipient.objects.create(message=msg, recipient_content_type=company_ct, recipient_id=company.pk) 
>>> MessageRecipient.objects.count() 
2 

आप देख सकते हैं , यह एक बहुत अधिक verbose (जटिल?) समाधान है। मैं शायद इसे सरल रखूंगा और उपरोक्त प्रारिडॉग के समाधान के साथ जाऊंगा।

+0

वाह। यह एक अच्छा समाधान है। बहुत verbose नहीं है लेकिन Prairiedogg की तुलना में एक डिग्री अधिक जटिल है। बहुत बहुत धन्यवाद –

+0

'क्लाइंट 'मॉडल में, मुझे समझ में नहीं आता कि क्यों' MessageRecipient'' rece_messages = जेनेरिक में है।जेनेरिकरेलेशन ('संदेश रेजिएंट', ...) '? क्या इसे 'संदेश' होना चाहिए? – user3595632

+1

@ user3595632 'rece_messages'' ग्राहक 'और' संदेश' के बीच कई से अधिक संबंध है। यही कारण है कि इसे 'MessageRecipient' पर होना चाहिए, जो उस रिश्ते को स्पष्ट रूप से मॉडल करता है, क्योंकि वहां कोई' जेनेरिकमनी टोमनीफिल्ड्स 'नहीं है। क्या इसका कोई मतलब है? – elo80ka

4

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

from django.db import models 
from django.utils.translation import ugettext_lazy as _ 

class Client(models.Model): 
    PERSON, CORPORATION = range(2) 
    CLIENT_TYPES = (
        (PERSON, _('Person')), 
        (CORPORATION, _('Corporation')), 
        ) 
    type = models.PositiveIntegerField(choices=CLIENT_TYPES, default=PERSON) 
    city = models.CharField(max_length=16) 
    first_name = models.CharField(max_length=16, blank=True, null=True) 
    last_name = models.CharField(max_length=16, blank=True, null=True) 
    corporate_name = models.CharField(max_length=16, blank=True, null=True) 
    tax_no = models.PositiveIntegerField(blank=True, null=True) 

    def save(self, *args, **kwargs): 
     """ 
     Does some validation ensuring that the person specific fields are 
     filled in when self.type == self.PERSON, and corporation specific 
     fields are filled in when self.type == self.CORPORATION ... 

     """ 
     # conditional save logic goes here 
     super(Client, self).save(*args, **kwargs) 

यदि आप चीजें करते हैं तो आपको जेनेरिक विदेशी कुंजी के साथ गड़बड़ नहीं करना पड़ सकता है। एक अतिरिक्त सुविधा के रूप में आप क्लाइंट मॉडल के लिए कस्टम प्रबंधक भी लिख सकते हैं जैसे Client.corporate.all(), Client.person.all(), पूर्व-फ़िल्टर किए गए क्वेरीसेट्स को वापस करने के लिए जो आप चाहते हैं केवल क्लाइंट के प्रकार।

यह आपकी समस्या को हल करने का सबसे अच्छा तरीका भी नहीं हो सकता है। मैं इसे एक संभावित संभावना के रूप में बाहर फेंक रहा हूं। मुझे नहीं पता कि डेटा समानता सुनिश्चित करने के लिए दो समान मॉडल को एक साथ जोड़ने और सहेजने के ओवरराइड का उपयोग करने के बारे में पारंपरिक ज्ञान है या नहीं। ऐसा लगता है कि यह संभावित रूप से समस्याग्रस्त हो सकता है ... मैं समुदाय को इस पर सीखने दूँगा।

+0

धन्यवाद @Prairiedogg। आपने जो भी कहा है उससे सहमत हैं। अभी भी यह देखने में दिलचस्पी है कि सामान्य संबंधों का उपयोग कर कोई समाधान है ... –

3

इस बारे में जाने के लिए पूर्ण सबसे अच्छा तरीका है तो फिर एक पुस्तकालय बुलाया Django-gm2m

pip install django-gm2m 

उपयोग करने के लिए करता है, तो हम अपने मॉडल

>>> from django.db import models 
>>> 
>>> class Video(models.Model): 
>>>  class Meta: 
>>>   abstract = True 
>>> 
>>> class Movie(Video): 
>>>  pass 
>>> 
>>> class Documentary(Video): 
>>>  pass 

और एक उपयोगकर्ता है

>>> from gm2m import GM2MField 
>>> 
>>> class User(models.Model): 
>>>  preferred_videos = GM2MField() 

हम

कर सकते हैं

मीठे अधिकार?

अधिक जानकारी के लिए यहां जाएं:

http://django-gm2m.readthedocs.org/en/stable/quick_start.html

संबंधित मुद्दे