一个子类化 abc 的 django 模型,给出了元类冲突

Posted

技术标签:

【中文标题】一个子类化 abc 的 django 模型,给出了元类冲突【英文标题】:A django model that subclasses an abc, gives a metaclass conflict 【发布时间】:2012-02-02 03:56:07 【问题描述】:

我有以下模型和抽象基类

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)

但我不太喜欢这种方法,因为它看起来像猴子补丁。

还有其他方法可以解决这个问题吗?

我尝试将模型元类显式分配给 Child,但它不起作用。 我不是在寻找通过编写代码来解决它的方法。我认为这必须通过改变我的班级结构来解决。

【问题讨论】:

我认为你将不得不创建一个新的元类来做 django 和 abc 的事情,可能通过按顺序调用它们各自的元类,也许使用继承。 使用 abs.register 方法并没有什么不好的地方——它就是为这些情况而设计的。顺便说一句,Python 的思维方式已经完成,所以你很少应该需要接口之类的——也许你太受静态语言的方式限制了? @jsbueno - 你可能是对的,但我需要以某种方式实现接口功能。这是一个示例植入-gist.github.com/1559689。有没有更好的方法来实现这个功能,在 python 中? 【参考方案1】:

除了创建一个继承自ABCMetaModelBase 的新元类,或使ABCMeta 继承自ModelBase您无能为力。 p>

但是,不同的注册模式可能是合适的吗? 可能是 contrib.admin.autodiscover 之类的? 或者类装饰器?或者.py 文件底部的循环在适当的类(例如for var in globals().values(): if isinstance(var, type) and issubclass(var, AbastractBase): register(var))上调用register

编辑:哦。我假设ABCMeta 是一个例子,而不是ABCMeta。这就是我在睡眠太少的情况下浏览 *** 的结果。

【讨论】:

我的结论是如果我使用 abc 作为接口,我应该使用 abc.register。我真的认为应该有更好的方法来实现接口(@98​​7654322@)。没有它们,python 的 oo 特性对我来说似乎很弱。 如果你觉得这“让 Python 的 OO 变弱了”,那么我可能会谦虚地建议你对“强 OO 的要求”的理解与 Python 的设计者的理解有很大的不同(或者你不小心输入了“ oo”当您打算输入“静态类型检查”时?)

以上是关于一个子类化 abc 的 django 模型,给出了元类冲突的主要内容,如果未能解决你的问题,请参考以下文章

为 django 1.5 自定义用户模型子类化 django-registration 1.0 表单

你如何在 django 中扩展站点模型?

无法从超类访问 Django 模型的子类

如何在 Django 模型上存储字典?

Django模型继承:使用现有超类创建子类

将子类模型实例转换为 django 中的另一个子类模型实例?