Integration with django-mptt

When you have to combine TranslatableModel with MPTTModel you have to make sure the model managers of both classes are combined too.

This can be done by extending the Manager and QuerySet class.

Note

This example is written for django-mptt >= 0.7.0, which also requires combining the queryset classes.

For a working example, see django-categories-i18n.

Combining TranslatableModel with MPTTModel

Say we have a base Category model that needs to be translatable:

from django.db import models
from django.utils.encoding import force_text
from parler.models import TranslatableModel, TranslatedFields
from parler.managers import TranslatableManager
from mptt.models import MPTTModel
from .managers import CategoryManager


class Category(MPTTModel, TranslatableModel):
    # The shared base model. Either place translated fields here,
    # or place them at the subclasses (see note below).
    parent = models.ForeignKey('self', related_name='children')

    translations = TranslatedFields(
        name=models.CharField(blank=False, default='', max_length=128),
        slug=models.SlugField(blank=False, default='', max_length=128)
    )

    objects = CategoryManager()

    def __str__(self):
        return self.safe_translation_getter('name', any_language=True)

Combining managers

The managers can be combined by inheriting them:

from parler.managers import TranslatableManager, TranslatableQuerySet
from mptt.managers import TreeManager
from mptt.querysets import TreeQuerySet


class CategoryQuerySet(TranslatableQuerySet, TreeQuerySet):

    def as_manager(cls):
        # make sure creating managers from querysets works.
        manager = CategoryManager.from_queryset(cls)()
        manager._built_with_as_manager = True
        return manager
    as_manager.queryset_only = True
    as_manager = classmethod(as_manager)


class CategoryManager(TreeManager, TranslatableManager):
    _queryset_class = CategoryQuerySet

Assign the manager to the model objects attribute.

Implementing the admin

By merging the base classes, the admin interface supports translatable MPTT models:

from django.contrib import admin
from parler.admin import TranslatableAdmin, TranslatableModelForm
from mptt.admin import MPTTModelAdmin
from mptt.forms import MPTTAdminForm
from .models import Category


class CategoryAdminForm(MPTTAdminForm, TranslatableModelForm):
    pass


class CategoryAdmin(TranslatableAdmin, MPTTModelAdmin):
    form = CategoryAdminForm

    def get_prepopulated_fields(self, request, obj=None):
        return {'slug': ('title',)}  # needed for translated fields


admin.site.register(Category, CategoryAdmin)