【发布时间】:2023-03-23 15:13:01
【问题描述】:
到目前为止,关于 SO 的所有其他答案都以完全相同的方式回答:构建您的元类,然后继承这些元类的“加入”版本,即
class M_A(type): pass
class M_B(type): pass
class A(metaclass=M_A): pass
class B(metaclass=M_B): pass
class M_C(M_A, M_B): pass
class C:(A, B, metaclass=M_C): pass
但我不知道这些人生活在什么世界,他们在哪里构建您自己的元类!显然,一个人会使用其他库中的类,除非你对元编程有完美的处理,否则你怎么知道你是否可以覆盖一个类的元类? (显然我还没有掌握它们)。
我的问题是:
class InterfaceToTransactions(ABC):
def account(self):
return None
...
class Category(PolymorphicModel, InterfaceToTransactions):
def account(self):
return self.source_account
...
class Income(TimeStampedModel, InterfaceToTransactions):
def account(self):
return self.destination_account
...
这当然给了我错误:“元类冲突:派生类的元类必须是其所有基类的元类的(非严格)子类” 我已经尝试了上面给出的解决方案的许多变体,以下不起作用,给出了同样的错误。
class InterfaceToTransactionsIntermediaryMeta(type(PolymorphicModel), type(InterfaceToTransactions)):
pass
class Category(PolymorphicModel, InterfaceToTransactions):
__metaclass__ = InterfaceToTransactionsIntermediaryMeta
...
也没有在类 Meta 函数中添加任何内容。我已阅读有关此主题的所有其他 SO 问题,请不要简单地将其标记为重复。
-------在接受解决方案后于 1/8/18 编辑-------
奇怪的是,如果我尝试使用这个新配置(我接受的配置)进行迁移,它会再次开始给出元类错误,但它在运行时仍然有效。如果我注释掉元类部分然后 makemigrations 并迁移,它会成功执行,但是每次迁移后我都必须将它放回那里。
【问题讨论】:
-
只是为了澄清,您需要它使您的
Category和Income都继承自InterfaceToTransactions,其中抽象方法account是?如果仅此而已,使用 Metaclass 有点矫枉过正...... -
我已经缩短了这里的定义,但是对于每个使用接口的类来说,都有相当多的冗长方法。
-
@mastachimp 你找到解决
migrate/makemigrations问题的方法了吗? -
@mastachimp 我注意到如果您在新数据库上运行
python manage.py migrate没有问题,但随后的运行会中断。 -
这似乎是 Django 中的一个已知错误,但他们尚未就一个好的解决方案达成一致:code.djangoproject.com/ticket/25068
标签: python django metaclass abc django-polymorphic