2010-06-24 16 views
7

निम्नलिखित कोड दिया जाता है पूछताछ की उपवर्ग प्राप्त करें:Django मॉडल उपवर्गीकरण: सुपर क्लास

class BaseMedium(models.Model): 
    title = models.CharField(max_length=40) 
    slug = models.SlugField() 

class A(BaseMedium): 
    url = models.URLField() 

class B(BaseMedium): 
    email = models.EmailField() 

मैं अब हर BaseMedium क्वेरी करना चाहते हैं।

b = BaseMedium.objects.all() 

सबक्लास प्रकार के बारे में जानने के बिना सबक्लास फ़ील्ड समेत प्रत्येक जानकारी को मैं कैसे प्रिंट करूं?

b[0].a जानकारी प्रिंट होता अगर b[0] वास्तव में एक A उदाहरण से संबंधित है लेकिन अगर यह B से संबंधित है यह एक DoesNotExist अपवाद प्रिंट होगा।

यह समझ में आता है लेकिन मैं एक सामान्य चर या विधि चाहता हूं जो संबंधित वस्तु को वापस कर दे।

शायद मेरा डाटाबेस लेआउट उस तरह से पूछने के लिए वास्तव में बहुत अच्छा नहीं है अगर ऐसा है तो यदि आप बेहतर लेआउट की सिफारिश करेंगे तो मुझे खुशी होगी।

मैं एक GenericForeignKey

class Generic(models.Model): 
    basemedium = models.ForeignKey('BaseMedium') 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    object = generic.GenericForeignKey('content_type', 'object_id') 

का उपयोग कर के बारे में सोचा लेकिन इस समाधान जटिल करने के लिए हो रहा है और मुझे लगता है कि तुम लोग बेहतर समाधान है।

उत्तर

2

ऐसा करने का एकमात्र तरीका आधार मॉडल पर स्पष्ट रूप से स्टोर करना है कि यह किस प्रकार है। तो बेसमेडियम पर derived_type (या जो कुछ भी) फ़ील्ड है, और इसे सहेजने पर सेट करें। फिर आपके पास get_derived_type विधि हो सकती है:

def get_derived_type(self): 
    if self.derived_type == 'A': 
     return self.a 
    elif self.derived_type == 'B': 
     return self.b 

और इसी तरह।

1

धन्यवाद श्रीमान। आपके उत्तर के लिए Roseman। मैंने आपके विचार को थोड़ा और विकसित किया।

def related_object(self, default_pointer_name='_ptr'): 
     models = [A,B] #models 
     object = None 

     argument = '%s%s' %(self.__class__.__name__.lower(), default_pointer_name) 
     query = { argument : self} 

     for model in models: 
      try: 
       object = model.objects.get(**query) 
      except model.DoesNotExist: 
       pass 
      else: 
       return object 

     if object == None: 
      raise RelatedObjectException 
     return object 

यह BaseMedium द्वारा इस्तेमाल किया एक विधि है: यहाँ मैं के साथ आया है।

+0

आपको इस से सावधान रहना चाहिए। यदि आपके पास डीबी से पुनर्प्राप्त करने के लिए 1000 रिकॉर्ड हैं तो यह एक चयन में किया जाएगा लेकिन फिर प्रत्येक बेसमेडियम ऑब्जेक्ट के लिए उप प्रकार प्राप्त करने के लिए यह 1000 एकल चयन होगा। वैसे भी मुझे बेहतर विचार नहीं पता कि यह कैसे करना है। मैं कुछ सिमिलर का उपयोग करता हूं, जो बहुत से अतिरिक्त डीबी प्रश्नों का उत्पादन करता है ... – dzida

+1

शूट आप सही हैं। कस्टम एसक्यूएल एक विकल्प हो सकता है ... अजीब बात यह है कि मुझे नहीं पता कि यह ज्ञात समाधान के साथ एक आम समस्या नहीं है। – rotrotrot

3

आपको कुछ समय पहले समाधान posted by Carl Meyer समाधान देखना चाहिए। यह आंतरिक रूप से ContentType दृष्टिकोण का उपयोग करता है, लेकिन यह इसे बहुत सुंदर ढंग से encapsulates।

वह एक वैकल्पिक और अधिक कुशल समाधान को भी इंगित करता है, जिसे डेटाबेस पर एक अतिरिक्त क्षेत्र को स्टोर करने की आवश्यकता नहीं है, लेकिन यह केवल प्रत्यक्ष बाल कक्षाओं के लिए ही काम करेगा। यदि आपके पास कई विरासत स्तर हैं, तो पहला समाधान बेहतर है।

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