双重继承导致元类冲突。

7

我使用两个 Django 包 - django-mptt(用于实现修改后的先序树遍历的工具)和 django-hvad(模型翻译)。

我有一个模型类 MenuItem,我想让它扩展 TranslatableModel 和 MPTTModel,就像这样:

class MenuItem(TranslatableModel, MPTTModel):

但它会导致元类冲突:

(TypeError: Error when calling the metaclass bases 
metaclass conflict: the metaclass of a derived class 
must be a (non-strict) subclass of the metaclasses of all its bases)

这个问题的解决方案是什么?我希望可以使用双重继承。

为什么需要多重继承?如果可以避免,最好不要使用它。 - jathanism
由于MenuItem具有多语言翻译(需要扩展TranslatableModel),并且必须具有树形层次结构(需要扩展MPTTModel)。 - David Silva
1
相关链接:https://dev59.com/tmw15IYBdhLWcg3whMK_#7314847 - jathanism
1
MPTTModel具有元类MPTTModelBase,而TranslatableModel具有元类TranslatableModelBase。就像@jathanism链接中的答案一样,您必须设置元类,因为Python不知道要使用哪个基类的元类。 - Jeremy Pridemore
可能是三重继承有时会导致元类冲突的重复问题。 - JMax
3个回答

5
您可能想要做以下事情:
class CombinedMeta(TranslatableModel.__metaclass__, MPTTModel.__metaclass__):
    pass
class MenuItem(TranslatableModel, MPTTModel):
    __metaclass__=CombinedMeta

这样做可以准确地得到你想要的结果,而没有任何错误信息。

在这种情况下,MenuItem.objects 将是翻译管理器。为了添加树管理器,必须手动添加 - tobjects = TreeManager() - miki725

2

非常抱歉回复晚了,但我认为这将有助于遇到相同问题的人。当您子类化MPTTModel和另一个类时,请确保先放置MPTTModel,像这样:

class MenuItem(MPTTModel, TranslatableModel):

这是文档推荐的做法 - Hamish Downer

1

一般来说,@schacki的答案是可行的。然而,django-hvad在幕后覆盖了许多其他的manager/queryset类,这使得目前无法与django-mptt/django-polymorphic及其它友好的包集成。

看一下django-parler,它具有与django-hvad相似的API和管理界面集成,并且还可以与其他包良好地协作。表格布局是相同的,因此您应该能够轻松切换包。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接