2009-12-11 10 views
5

मैं एक Django ऐप बना रहा हूं जो इसके मॉडल में कुछ विरासत का उपयोग करता है, मुख्य रूप से क्योंकि मुझे सबकुछ यूयूआईडी और संदर्भ निर्दिष्ट करने की आवश्यकता है, इसलिए मुझे पता है कि यह कौन सा वर्ग था।पायथन और डीजेगो में विरासत और कारखाने के कार्यों

class BaseElement(models.Model): 
    uuid = models.CharField(max_length=64, editable=False, blank=True, default=lambda:unicode(uuid4())) 
    objmodule = models.CharField(max_length=255, editable=False, blank=False) 
    objclass = models.CharField(max_length=255, editable=False, blank=False) 

class ChildElement(BaseElement): 
    somefield = models.CharField(max_length=255) 

मुझे यकीन है कि objmodule, objclass, और UUID स्वचालित रूप से स्थापित कर रहे हैं करना चाहते हैं: यहाँ आधार वर्ग का एक सरलीकृत संस्करण है। मैंने this post से सीखा है कि यह मेरा खुद का कन्स्ट्रक्टर लिखकर ऐसा करना एक बुरा विचार है, और मैं एक फैक्ट्री फ़ंक्शन लिखने से बेहतर हूं। तो अब मेरा बेस एलिमेंट और चाइल्ड एलिमेंट इस तरह दिखता है:

class BaseElement(models.Model): 
    uuid = models.CharField(max_length=64, editable=False, blank=True, default=lambda:unicode(uuid4())) 
    objmodule = models.CharField(max_length=255, editable=False, blank=False) 
    objclass = models.CharField(max_length=255, editable=False, blank=False) 

    def set_defaults(self): 
     self.objmodule = unicode(self.__class__.__module__) 
     self.objclass = unicode(self.__class__.__name__) 
     self.uuid = unicode(uuid4()) 

class ChildElement(BaseElement): 
    somefield = models.CharField(max_length=255) 

    @staticmethod 
    def create(*args, **kwargs): 
     ce = ChildElement(*args, **kwargs) 
     ce.set_defaults() 
     return ce 

यह काम करता है। मैं ChildElement.create(somefield="foo") पर कॉल कर सकता हूं और मुझे uuid, objmodule, और objclass फ़ील्ड सही सेट के साथ एक उचित वस्तु मिल जाएगी। हालांकि, जैसा कि मैं ChildElement2 और ChildElement3 जैसे अधिक कक्षाएं बना रहा हूं, मुझे लगता है कि मैं सटीक वही स्थिर फैक्ट्री फ़ंक्शन डाल रहा हूं। यह मुझ पर गले लगाता है क्योंकि कोड डुप्लिकेशन खराब है।

सामान्य तरीकों के साथ मैं सिर्फ BaseElement में create कारखाने समारोह सम्मिलित था, हालांकि, मुझे लगता है कि यहाँ ऐसा नहीं कर सकते, क्योंकि मैं (क्योंकि यह अभी तक नहीं बनाया गया है) आत्म करने के लिए एक संभाल की जरूरत नहीं है पाने के लिए उस वस्तु के वर्ग के बारे में जानकारी जिसने विधि को बुलाया था।

वहाँ एक रास्ता है कि मैं BaseElement वर्ग में इस कारखाने की ओर पलायन कर सकते हैं तो मैं हर जगह इस कोड को नकल करने की जरूरत नहीं है और अभी भी यह किया है तो यह स्वचालित रूप से की uuid, objmodule, और objclass मान सेट है?

उत्तर

7

आप create() एक @classmethod@staticmethod के बजाय बनाने हैं, तो आप वर्ग वस्तु है, जो आप के बजाय नाम से यह जिक्र का उपयोग कर सकते हैं का लाभ उठा सकेंगे प्रत्येक बच्चे वर्ग की बजाय बेस क्लास पर।

+1

यह वही है जो मैं ढूंढ रहा था। मुझे '@ classmethod' के बारे में याद दिलाने के लिए धन्यवाद। यह ऐसा कुछ नहीं है जिसका मैं अक्सर उपयोग करता हूं। – Pridkett

+0

पायथन में '@ staticmethod' के लिए शायद ही कभी एक अच्छा उपयोग मामला है - यही वह है जिसे आप शायद कम से कम उपयोग करते हैं, यदि कभी भी। अक्सर अगर कुछ '@ classmethod' नहीं है तो यह मॉड्यूल में एक सरल शीर्ष-स्तरीय फ़ंक्शन के रूप में अधिक उपयुक्त है। –

2

मुझे लगता है कि आप इसके बजाय अपने बेसलेमेंट में ओवरराइडिंग को बेहतर तरीके से बंद कर सकते हैं। फिर सहेजने पर आप उन फ़ील्ड को सेट कर सकते हैं। यह कुछ ऐसा होगा:

class MyBase(models.Model): 
    uuid = models.CharField(max_length=64, editable=False, blank=True, 
     default=lambda:unicode(uuid4())) 
    objmodule = models.CharField(max_length=255, editable=False, blank=False) 
    objclass = models.CharField(max_length=255, editable=False, blank=False) 

    def save(self): 
     if not self.id: 
      self.objmodule = unicode(self.__class__.__module__) 
      self.objclass = unicode(self.__class__.__name__) 
      self.uuid = unicode(uuid4()) 
     super(self.__class__.__base__, self).save() 

class InheritedFromBase(MyBase): 
    new_field = models.CharField(max_length=100) 

मैंने इसका परीक्षण किया और ऐसा लगता है कि आप जो खोज रहे हैं। मैं एक "इनहेरेटेड फ्रॉमबेस" ऑब्जेक्ट बनाने में सक्षम था जिसमें आपके पास आवश्यक फ़ील्ड थे, बिना कोड डुप्लिकेशंस के।

@classmethod 
def create(cls, *args, **kwargs): 
    obj = cls(*args, **kwargs) 
    obj.set_defaults() 
    return obj 

यह अब सामान्य है और जा सकते हैं:

+0

+1: बस 'सेव' ओवरराइड करना हमेशा सही काम करना है। –

+1

यह करीब है, और यह स्वीकार्य साबित हो सकता है, लेकिन मुझे जो चाहिए वह काफी नहीं है। अभी मैं सर्वर पर कुछ ऑब्जेक्ट्स बनाता हूं, फिर उन्हें AJAX ऐप में उपयोग के लिए क्लाइंट को क्रमबद्ध करता हूं। क्लाइंट गुणों को संशोधित कर सकता है और फिर वस्तुओं को सहेज सकता है। आपके सेटअप के साथ उन्हें 'uuid', 'objmodule', और' objclass' को तब तक असाइन नहीं किया जाएगा जब तक वे सहेजे नहीं जाते हैं। चूंकि मैं क्लाइंट पर 'uuid' का उपयोग करता हूं, मुझे शायद सर्वर पर कुछ अतिरिक्त तर्क जोड़ने की आवश्यकता होगी, या क्लाइंट इसे असाइन कर सकता है। तो करीब है, लेकिन मैं पहले 'save' का आह्वान किए बिना एक रास्ता खोजना चाहता हूं। हालांकि, अगर यह सही तरीका है तो मैं सौदा कर सकता हूं। – Pridkett

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