2012-11-27 21 views
5

मैं Django-tastypie उपयोग कर रहा हूँ और मैं अपने Django मॉडल से इस तरह कक्षाएं बनाने के लिए की जरूरत है:अजगर गतिशील आंतरिक वर्ग के साथ वर्ग बनाने

class MyModelResource(ModelResource): 
    class Meta: 
     queryset = MyModel.objects.all() 
     allowed_methods = ['get'] 

जब से मैं मैं अपने Django एप्लिकेशन डॉन में मॉडल का एक बहुत कुछ है खुद को दोहराना नहीं चाहता, और सभी संसाधन वर्गों को बनाने के लिए टाइप() फ़ंक्शन का उपयोग करें। समस्या यह है कि मुझे नहीं पता कि इस आंतरिक "मेटा" वर्ग से कैसे निपटें।

क्या आप मुझे उदाहरण दे सकते हैं कि प्रकार() का उपयोग करके आंतरिक वर्ग के साथ गतिशील रूप से कक्षा कैसे बनाएं?

उत्तर

7
class MyModel(object) : pass 
modelClass = MyModel() 

class ModelResource(object): 
    def mymethod(self): 
     print('got here') 

Meta = type('Meta', (object,), {'allowed_methods': ['get']}) 

def add_mymethod(cls): 
    def mymethod(self): 
     super(cls, self).mymethod() 
    cls.mymethod = mymethod 
    return cls 

name = modelClass.__class__.__name__ + "Resource" 
MyModelResource = add_mymethod(type(name, (ModelResource,), 
            {'Meta':Meta, })) 

print(MyModelResource.Meta) 
# <class '__main__.Meta'> 

m = MyModelResource() 
m.mymethod() 
# got here 

भीतरी वर्ग, Meta, जहाँ तक MyModelResource का सवाल है सिर्फ एक और विशेषता है।


तरीके बस के रूप में जहाँ तक MyModelResource संबंध है विशेषताओं का भी कर रहे हैं। असल में, आप MyModelResource.__dict__ में एक समारोह परिभाषित करते हैं, और अजगर विशेषता देखने तंत्र inst.mymethod का कारण बनता है एक बाध्य विधि वापस जाने के लिए।

वहाँ super कॉल

super(MyModelResource, self).mymethod() 
MyModelResource से पहले

परिभाषित किया गया है में MyModelResource की चर्चा करते हुए कोई समस्या नहीं है, क्योंकि नाम लुकअप समय mymethod परिभाषित किया गया है पर नहीं, रन टाइम पर प्रदर्शन कर रहे हैं है।


आप बिल्कुल सही है कि

super(self.__class_, self).mymethod() 

गलत है कर रहे हैं। इससे super के बारे में अच्छा सब कुछ खराब हो जाएगा। यदि MyModelResource को उप-वर्गीकृत किया जाना था, और सबक्लास का एक उदाहरण mymethod पर कॉल करना था, तो पायथन एक अनंत लूप में गिर जाएगा।

+0

यह सही उत्तर है। अब, अगर मुझे उस विधि को परिभाषित करना है जो सुपर() अंदर कॉल करता है? मैं सुपर (स्वयं .__ वर्ग__, स्वयं) लिखने से बचना चाहता हूं क्योंकि स्पष्ट रूप से एक अच्छा विचार नहीं है ... – mnowotka

+0

समस्या यह है कि मुझे परिभाषित विधि के समय कक्षा का नाम नहीं पता है। मेरे मामले में कक्षा का निर्माण इस तरह दिखता है: टाइप (modelClass .__ वर्ग __.__ name__ + "संसाधन", (मॉडल रिसोर्स,), {"मेटा" ... तो मैं इसे विधि में नाम से संदर्भित नहीं कर सकता। – mnowotka

+0

ठीक है, तो 'mymethod' को तब तक परिभाषित नहीं किया जा सकता जब तक कि 'MyModelResource' परिभाषित नहीं किया जाता है। उस स्थिति में, एक वर्ग सजावट का उपयोग करें। मैंने कक्षा सजावटकर्ता,' add_mymethod' को एक उदाहरण के रूप में जोड़ा है। – unutbu

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