2012-01-04 32 views
7

我有以下模型和抽象基類的子類的ABC一個Django模型,給出了一個元類衝突

import abc 
from django.db import models 


class AbstractBase(): 
    __metaclass__ = abc.ABCMeta 

    @abc.abstractmethod 
    def my_method(self): 
     return 


class MyModel(models.Model, AbstractBase): 
    @abc.abstractmethod 
    def my_method(self): 
     return 1 

但我收到以下錯誤。

元類衝突:一個派生類的元類必須是其所有基地的元類的 (非嚴格)子

我覺得這裏的問題是(正如本文所描述http://code.activestate.com/recipes/204197-solving-the-metaclass-conflict/)兩個基類有兩個不同的元類,所以python無法決定哪個元類用於子對象。

爲了解決這個問題,我刪除多個傳承與使用下列註冊方法來註冊子類

abc.register(Child) 

但我真的不喜歡這種方法,因爲它看起來像猴修補。

有沒有解決這個問題的另一種方法?

我嘗試將模型元類明確地分配給子,但它沒有工作。 我不想通過編寫代碼來解決這個問題。我認爲這必須通過改變我的班級結構來解決。

+0

我想你將不得不創建一個新的元類,既可以同時執行django和abc的東西,也可以按順序調用它們各自的元類,也許可以使用繼承。 – cha0site 2012-01-04 08:14:51

+0

對於使用abs.register方法沒有什麼不妥之處 - 它正是爲這些情況而設計的。順便說一句,Python的思維方式已經完成了,所以你很少應該使用_need_接口等等 - 也許你被靜態語言中的事情束縛住了嗎? – jsbueno 2012-01-04 10:12:08

+0

@jsbueno - 您可能是對的,但我需要以某種方式實現接口功能。這是一個植入示例 - https://gist.github.com/1559689。有沒有更好的方式來實現這個功能,在python中? – yilmazhuseyin 2012-01-04 11:41:58

回答

2

除了建立一個新的元類來自兩個ABCMetaModelBase繼承或ModelBase使ABCMeta繼承,沒有什麼可以做。

但是,可能是不同的註冊模式可能是合適的? 也許類似contrib.admin.autodiscover還是一個類裝飾器?或在.py文件底部的循環,在相應的類上調用register(例如,for var in globals().values(): if isinstance(var, type) and issubclass(var, AbastractBase): register(var))?

編輯:D'oh。我假設ABCMeta是一個例子,而不是ABCMeta。這就是我在睡眠過少時瀏覽StackOverflow的原因。

+0

我的結論是如果我使用abc作爲接口,我應該使用abc.register。我真的認爲應該有更好的方法來實現一個接口(http://www.python.org/dev/peps/pep-0245/)。沒有他們,Python的功能對我來說似乎很弱。 – yilmazhuseyin 2012-01-04 09:09:07

+3

如果你覺得這樣「使得Python的OO變弱」,那麼我可能會虛心地暗示你對「強OO的需求」的理解與Python設計者的差異很大(或者當你打算打字時意外鍵入「oo」 「靜態類型檢查」?) – 2012-01-04 16:40:03

相關問題