我需要根据某些条件创建一个使用不同基类的类.有些课程让我臭名昭着:
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
Run Code Online (Sandbox Code Playgroud)
一个例子是sqlite3,这是一个简单的例子,你甚至可以在解释器中使用:
>>> import sqlite3
>>> x = type('x', (sqlite3,), {})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
Run Code Online (Sandbox Code Playgroud) 到目前为止,关于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
Run Code Online (Sandbox Code Playgroud)
但我不知道这些人住在哪个世界,他们在哪里构建自己的元类!显然,一个人会使用其他库中的类,除非你对元编程有一个完美的处理,你怎么知道你是否可以覆盖一个类的元类?(显然我还没有处理它们).
我的问题是:
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
...
Run Code Online (Sandbox Code Playgroud)
这当然给了我错误:"元类冲突:派生类的元类必须是其所有基础的元类的(非严格)子类" 我已经尝试了上面给出的解决方案的许多变体,以下是不工作,给出同样的错误.
class InterfaceToTransactionsIntermediaryMeta(type(PolymorphicModel), type(InterfaceToTransactions)):
pass
class Category(PolymorphicModel, InterfaceToTransactions):
__metaclass__ = InterfaceToTransactionsIntermediaryMeta
...
Run Code Online (Sandbox Code Playgroud)
也没有把任何东西放在Meta函数中.我已经阅读了关于这个主题的每一个其他问题,请不要简单地将其标记为重复.
-------------------在接受解决方案后的1/8/18编辑-------
奇怪的是,如果我尝试使用这个新配置(我接受的那个)进行迁移,它会再次开始给出元类错误,但它仍然可以在运行时运行.如果我注释掉元类部件然后makemigrations并迁移,它会成功完成,但是每次迁移后我都必须把它放回去.
在 django 抽象类中似乎可以使用:
class Meta:
abstract = True
Run Code Online (Sandbox Code Playgroud)
但是我不知道如何在这些类中声明不包含任何逻辑的抽象方法/函数,例如
class AbstractClass(models.Model):
def abstractFunction():
class Meta:
abstract = True
Run Code Online (Sandbox Code Playgroud)
库 abc 的符号 @abstractmethod 似乎不适用于此处,还是我错了?