Third-party applications support¶
django-reversion support¶
Support for django-reversion works as expected with polymorphic models. However, they require more setup than standard models. That’s become:
- The children models are not registered in the admin site. You will therefore need to manually register them to django-reversion.
- Polymorphic models use multi-table inheritance.
See the reversion documentation
how to deal with this by adding a
follow
field for the primary key. - Both admin classes redefine
object_history_template
.
Example¶
The admin Example becomes:
from django.contrib import admin
from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin
from reversion.admin import VersionAdmin
from reversion import revisions
from .models import ModelA, ModelB, ModelC
class ModelAChildAdmin(PolymorphicChildModelAdmin, VersionAdmin):
base_model = ModelA
base_form = ...
base_fieldsets = (
...
)
class ModelBAdmin(ModelAChildAdmin, VersionAdmin):
# define custom features here
class ModelCAdmin(ModelBAdmin):
# define custom features here
class ModelAParentAdmin(VersionAdmin, PolymorphicParentModelAdmin):
base_model = ModelA
child_models = (
(ModelB, ModelBAdmin),
(ModelC, ModelCAdmin),
)
revisions.register(ModelB, follow=['modela_ptr'])
revisions.register(ModelC, follow=['modelb_ptr'])
admin.site.register(ModelA, ModelAParentAdmin)
Redefine a admin/polymorphic/object_history.html
template, so it combines both worlds:
{% extends 'reversion/object_history.html' %}
{% load polymorphic_admin_tags %}
{% block breadcrumbs %}
{% breadcrumb_scope base_opts %}{{ block.super }}{% endbreadcrumb_scope %}
{% endblock %}
This makes sure both the reversion template is used, and the breadcrumb is corrected for the polymorphic model.
django-reversion-compare support¶
The django-reversion-compare views work as expected, the admin requires a little tweak. In your parent admin, include the following method:
def compare_view(self, request, object_id, extra_context=None):
"""Redirect the reversion-compare view to the child admin."""
real_admin = self._get_real_admin(object_id)
return real_admin.compare_view(request, object_id, extra_context=extra_context)
As the compare view resolves the the parent admin, it uses it’s base model to find revisions. This doesn’t work, since it needs to look for revisions of the child model. Using this tweak, the view of the actual child model is used, similar to the way the regular change and delete views are redirected.
django-mptt support¶
Combining polymorphic with django-mptt is certainly possible, but not straightforward. It involves combining both managers, querysets, models, meta-classes and admin classes using multiple inheritance.
The django-polymorphic-tree package provides this out of the box.