7

I use two django packages - django-mptt (utilities for implementing Modified Preorder Tree Traversal) and django-hvad (model translation).

I have a model class MenuItem and I want to it extends TranslatableModel and MPTTModel, like this:

class MenuItem(TranslatableModel, MPTTModel):

but it causes metaclass conflict:

(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)

What is the solution this problem? I hope that I can use double inheritance.

Léo Léopold Hertz 준영
  • 134,464
  • 179
  • 445
  • 697
David Silva
  • 1,939
  • 7
  • 28
  • 60
  • Why do you need multiple inheritance? It's usually best to avoid it when you can. – jathanism Jun 29 '12 at 00:13
  • Because MenuItem has translations (need extends TranslatableModel) and must have tree hierarchy (need extends MPTTModel). – David Silva Jun 29 '12 at 00:18
  • 1
    Related: http://stackoverflow.com/a/7314847/194311 – jathanism Jun 29 '12 at 00:24
  • 1
    MPTTModel has metaclass MPTTModelBase and TranslatableModel has metaclass TranslatableModelBase. Just like the answer in the question that @jathanism linked to, you have to set your metaclass because Python doesn't know which base class' metaclass to use. – Jeremy Pridemore Jun 29 '12 at 00:34
  • possible duplicate of [Triple inheritance causes metaclass conflict... Sometimes](http://stackoverflow.com/questions/6557407/triple-inheritance-causes-metaclass-conflict-sometimes) – JMax Jul 25 '12 at 08:01

3 Answers3

5

You might want to do the following:

class CombinedMeta(TranslatableModel.__metaclass__, MPTTModel.__metaclass__):
    pass
class MenuItem(TranslatableModel, MPTTModel):
    __metaclass__=CombinedMeta

This should give you exactly what you want, without any error mesages.

schacki
  • 9,401
  • 5
  • 29
  • 32
  • In this case then `MenuItem.objects` will be the translation manager. In order to add tree manager, it has to be added manually - `tobjects = TreeManager()` – miki725 Mar 25 '13 at 03:49
2

Sorry for the late answer, but it i think it'll help for people who have same problem. When you subclass MPTTModel and another class, make sure you put MPTTModel first, like this:

class MenuItem(MPTTModel, TranslatableModel):
Otskimanot Sqilal
  • 2,332
  • 4
  • 21
  • 25
  • This is [what the docs recommend](https://django-mptt.github.io/django-mptt/models.html#setting-up-a-django-model-for-mptt) – Hamish Downer Nov 04 '16 at 10:31
1

Generally the answer of @schacki would work. However, django-hvad overrides many other manager/queryset classes under the hood, which makes integrating with django-mptt/django-polymorphic and friends impossible at the moment.

Take a look at django-parler, which features a similar API and admin integration as django-hvad, but plays nice with other packages too. The table layout is identical, so you should be able to switch the packages easily.

vdboor
  • 21,914
  • 12
  • 83
  • 96