2012-01-04 49 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

相关问题