2010-10-25 5 views
5

पर ले जाएं, मैं एक मौजूदा मॉडल को उप-वर्गीकृत कर रहा हूं। मैं अब माता-पिता वर्ग के कई सदस्यों को बाल वर्ग के सदस्य बनना चाहता हूं।एक पाइथन/django ऑब्जेक्ट को एक मूल मॉडल से बच्चे (उपclass)

उदाहरण के लिए, मेरे पास एक मॉडल निगल है। अब, मैं यूरोपीय Swallow (निगल) और अफ्रीकी Swallow (निगल) बना रहा हूँ। मैं कुछ लेना चाहता हूं लेकिन सभी निगल वस्तुएं उन्हें या तो यूरोपीय सावलो या अफ्रीकीसालोव बनाती हैं, भले ही वे प्रवासी हों या नहीं।

मैं उन्हें कैसे स्थानांतरित कर सकता हूं?

उत्तर

4

मुझे पता है कि यह बहुत बाद में है, लेकिन मुझे कुछ ऐसा करने की ज़रूरत है और मुझे बहुत कुछ नहीं मिला। मुझे कुछ स्रोत कोड here में दफन किया गया जवाब मिला, लेकिन एक उदाहरण क्लास-विधि भी लिखी जो पर्याप्त होगी।

class AfricanSwallow(Swallow): 

    @classmethod 
    def save_child_from_parent(cls, swallow, new_attrs): 
     """ 
     Inputs: 
     - swallow: instance of Swallow we want to create into AfricanSwallow 
     - new_attrs: dictionary of new attributes for AfricanSwallow 

     Adapted from: 
     https://github.com/lsaffre/lino/blob/master/lino/utils/mti.py 
     """ 
     parent_link_field = AfricanSwallow._meta.parents.get(swallow.__class__, None) 
     new_attrs[parent_link_field.name] = swallow 
     for field in swallow._meta.fields: 
      new_attrs[field.name] = getattr(swallow, field.name) 
     s = AfricanSwallow(**new_attrs) 
     s.save() 
     return s 

मुझे पता नहीं लगा कि इस विधि के साथ काम करने के लिए मेरे फॉर्म सत्यापन को कैसे प्राप्त किया जाए; तो यह निश्चित रूप से और अधिक सुधार किया जा सकता है; शायद इसका मतलब है कि एक डेटाबेस रिफैक्टरिंग सबसे अच्छा दीर्घकालिक समाधान हो सकता है ...

+0

हे - कमाल का जवाब। यह थोड़ी देर हो गया है क्योंकि मुझे इसकी आवश्यकता थी। स्वाभाविक रूप से, मैं उत्पादन स्थिति में _meta पर भरोसा करने के लिए थोड़ा अनिच्छुक हूं, लेकिन ऐसा जीवन है। धन्यवाद! – jMyles

7

यह एक हैक का एक सा है, लेकिन यह काम करता है:

swallow = Swallow.objects.get(id=1) 
swallow.__class__ = AfricanSwallow 
# set any required AfricanSwallow fields here 
swallow.save() 
+0

क्या एक सुंदर हैक, यह मुझे एक दिन बचा लिया मदद मिलेगी बनाया जाएगा: यह मैं क्या किया है । धन्यवाद! – neelix

0

मैं django-model-utils's InheritanceCastModel उपयोग करने का सुझाव। यह एक ऐसा क्रियान्वयन है जिसे मैं पसंद करता हूं। आप djangosnippets और कुछ ब्लॉगों में कई और पा सकते हैं, लेकिन उन्हें मुश्किल होने के बाद मैंने इसे चुना है। आशा करता हूँ की ये काम करेगा।

1

इस बात पर निर्भर करता है कि आप किस प्रकार की मॉडल विरासत का उपयोग करेंगे। तीन क्लासिक प्रकारों के लिए http://docs.djangoproject.com/en/dev/topics/db/models/#model-inheritance देखें। चूंकि ऐसा लगता है कि आप सार तत्वों को निगलना चाहते हैं जो सार बेस क्लास को नियंत्रित करते हैं।

यदि आप निगल बनाम अफ्रीकीसावलो बनाम यूरोपीय सावलो के लिए डीबी में विभिन्न जानकारी स्टोर करना चाहते हैं, तो आप एमटीआई का उपयोग करना चाहेंगे। आधिकारिक डीजेंगो मॉडल के रूप में एमटीआई के साथ सबसे बड़ी समस्या यह है कि बहुरूपता ठीक तरह से काम नहीं करती है। यही है, अगर आप डीबी से एक निगल वस्तु प्राप्त करते हैं जो वास्तव में एक अफ्रीकीसावालो वस्तु है, तो आपको अफ्रीकीसालोव का एक उदाहरण नहीं मिलेगा। (this question देखें।) Django-model-utils InheritanceManager जैसे कुछ ऐसा करने में मदद कर सकते हैं।

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

0

एक और (पुराना) दृष्टिकोण: यदि आपको माता-पिता की आईडी रखने में कोई फर्क नहीं पड़ता है तो आप केवल माता-पिता के अटैचर्स से ब्रांड नए बाल उदाहरण बना सकते हैं।

ids = [s.pk for s in Swallow.objects.all()] 
# I get ids list to avoid memory leak with long lists 
for i in ids: 
    p = Swallow.objects.get(pk=i) 
    c = AfricanSwallow(att1=p.att1, att2=p.att2.....) 
    p.delete() 
    c.save() 

एक बार यह, चलाता है एक नया AfricanSwallow उदाहरण प्रत्येक प्रारंभिक निगल उदाहरण की जगह हो सकता है कि यह किसी को :)