2012-11-27 60 views
5

我使用的Django tastypie,我需要從我的Django模型創建類是這樣的:蟒蛇動態創建類的內部類

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

自從我在Django應用程序我不有很多車型我不想重複自己,而是使用type()函數來創建所有的資源類。問題是我不知道如何處理這個內在的「元」類。

你可以給我一個如何使用type()動態創建一個帶有內部類的類的例子嗎?

回答

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__中定義了函數,並且Python屬性查找機制 導致inst.mymethod返回方法的綁定

有一個在super通話

super(MyModelResource, self).mymethod() 
MyModelResource

定義指MyModelResource沒有問題,因爲名稱查找在運行時進行,而不是在被定義mymethod的時間。


你是絕對正確的,

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

是錯誤的。這將損壞所有關於super的好消息。如果MyModelResource將被子類化,並且子類的一個實例將調用mymethod,那麼Python將陷入無限循環。

+0

這是正確的答案。現在,如果我必須定義調用super()的方法呢?我想避免寫超(自我.__ class__,自我),因爲顯然不是一個好主意...... – mnowotka

+0

問題是我不知道在定義方法的時刻該類的名稱。在我的情況下,類的創建如下所示:type(modelClass .__ class __.__ name__ +「Resource」,(ModelResource,),{「Meta」...所以我不能在方法中用名稱引用它。 – mnowotka

+0

好吧,那麼'mymethod'只有在定義了MyModelResource之後才能定義,在這種情況下,請使用類裝飾器,我已經添加了類裝飾器add_mymethod作爲示例。 – unutbu