Permalink
Browse files

Added polymorphic admin interface

Extracted from django-fluent-pages, ready for other apps too.
The polymorphic admin is implemented via a parent admin for the base
model, and separate admin interfaces for the child models.

The parent model needs to inherit PolymorphicParentModelAdmin,
and override `get_admin_for_model()` and `get_child_model_classes()`
to find the child admin interfaces.

The derived models have their own `ModelAdmin` class, which inherits
from `PolymorphicChildModelAdmin`. The parent admin redirects it's
change and delete views to the child admin.

By adding `polymorphic` to the INSTALLED_APPS, the breadcrumbs will be
fixed as well, to remain unchanged between the child applications.
  • Loading branch information...
1 parent db4cc4d commit 5d65bf4bbc427561ddfa0149e04a5b3065e77499 @vdboor vdboor committed Jul 5, 2012
View
@@ -12,3 +12,4 @@ Contributors
* Charles Leifer (python 2.4 compatibility)
* Germán M. Bravo
* Martin Brochhaus
+* Diederik van der Boor (polymorphic admin interface)
View
@@ -3,6 +3,12 @@
Changelog
++++++++++
+Juli 5, 2012, Polymorphic admin interface
+=========================================
+
+Added a polymorphic admin interface. The admin interface is able to add polymorphic models,
+and the admin edit screen also displays the custom fields of the polymorphic model.
+
2011-12-20 Renaming, refactoring, new maintainer
================================================
View
@@ -153,6 +153,107 @@ In the examples below, these models are being used::
field3 = models.CharField(max_length=10)
+Using polymorphic models in the admin interface
+-----------------------------------------------
+
+Naturally, it's possible to register individual polymorphic models in the Django admin interface.
+However, to use these models in a single cohesive interface, some extra base classes are available.
+
+The polymorphic admin interface works in a simple way:
+
+* The add screen gains an additional step where the desired child model is selected.
+* The edit screen displays the admin interface of the child model.
+* The list screen still displays all objects of the base class.
+
+The polymorphic admin is implemented via a parent admin that forwards the *edit* and *delete* views
+to the ``ModelAdmin`` of the derived child model. Hence, both the parent model and child model
+need to have a ``ModelAdmin`` class. Only the ``ModelAdmin`` class of the parent/base model
+has to be registered in the Django admin site.
+
+The parent model
+~~~~~~~~~~~~~~~~
+
+The parent model needs to inherit ``PolymorphicParentModelAdmin``, and implement the following:
+
+* ``base_model`` should be set
+* ``get_admin_for_model()`` should return the model class for the child model.
+* ``get_child_model_classes()`` should return a list of all child model classes.
+
+The exact implementation can depend on the way your module is structured.
+Either a plugin registration system, or configuration setting could be used.
+The parent admin redirects it's change and delete views to the child admin.
+
+The child models
+~~~~~~~~~~~~~~~~
+
+The admin interface of the derived models should inherit from ``PolymorphicChildModelAdmin``.
+Again, ``base_model`` should be set in this class as well.
+This class implements the following features:
+
+* It corrects the breadcrumbs in the admin pages.
+* It extends the template lookup paths, to look for both the parent model and child model in the ``admin/app/model/change_form.html`` path.
+* It allows to set ``base_form`` so the derived class will automatically include other fields in the form.
+* It allows to set ``base_fieldsets`` so the derived class will automatically display any extra fields.
+
+By adding ``polymorphic`` to the ``INSTALLED_APPS``, the breadcrumbs will be
+fixed as well, to stay the same for all child models.
+
+The standard ``ModelAdmin`` attributes ``form`` and ``fieldsets`` should rather be avoided at the base class,
+because it will hide any additional fields which are defined in the derived model. Instead,
+use the ``base_form`` and ``base_fieldsets`` instead. The ``PolymorphicChildModelAdmin`` will
+automatically detect the additional fields that the child model has, display those in a separate fieldset.
+
+
+Example
+~~~~~~~
+
+::
+
+ from django.contrib import admin
+ from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin
+
+
+ class ModelAParentAdmin(PolymorphicParentModelAdmin):
+ """ The parent model admin """
+ base_model = ModelA
+
+ def get_admin_for_model(self, model):
+ # just `return ModelAChildAdmin` would also work, if you don't customize anything.
+ return CHILD_ADMINS[model]
+
+ def get_child_model_classes(self, model):
+ return CHILD_ADMINS.keys()
+
+
+ # Only the parent needs to be registered:
+ admin.site.register(ModelA, ModelAParentAdmin)
+
+
+ class ModelAChildAdmin(PolymorphicChildModelAdmin):
+ """ Base admin class for all child models """
+ base_model = ModelA
+
+ # By using these `base_...` attributes instead of the regular ModelAdmin `form` and `fieldsets`,
+ # the additional fields of the child models are automatically added to the admin form.
+ base_form = ...
+ base_fieldsets = (
+ ...
+ )
+
+ class ModelBAdmin(ModelAChildAdmin):
+ # define custom features here
+
+ class ModelCAdmin(ModelBAdmin):
+ # define custom features here
+
+
+ # This could be replaced with a registration system:
+ CHILD_ADMINS = {
+ ModelB: ModelBAdmin,
+ ModelC: ModelCAdmin,
+ }
+
+
Filtering for classes (equivalent to python's isinstance() ):
-------------------------------------------------------------
Oops, something went wrong.

0 comments on commit 5d65bf4

Please sign in to comment.