Make the admin `base_model` setting optional.

It can be detected using get_base_polymorphic_model()
fix_request_path_info
Diederik van der Boor 2017-09-30 16:35:02 +02:00
parent 19497960c7
commit cf0cb2478f
5 changed files with 23 additions and 17 deletions

View File

@ -63,7 +63,7 @@ The models are taken from :ref:`advanced-features`.
class ModelAChildAdmin(PolymorphicChildModelAdmin): class ModelAChildAdmin(PolymorphicChildModelAdmin):
""" Base admin class for all child models """ """ Base admin class for all child models """
base_model = ModelA base_model = ModelA # Optional, explicitly set here.
# By using these `base_...` attributes instead of the regular ModelAdmin `form` and `fieldsets`, # 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. # the additional fields of the child models are automatically added to the admin form.
@ -75,13 +75,13 @@ The models are taken from :ref:`advanced-features`.
@admin.register(ModelB) @admin.register(ModelB)
class ModelBAdmin(ModelAChildAdmin): class ModelBAdmin(ModelAChildAdmin):
base_model = ModelB base_model = ModelB # Explicitly set here!
# define custom features here # define custom features here
@admin.register(ModelC) @admin.register(ModelC)
class ModelCAdmin(ModelBAdmin): class ModelCAdmin(ModelBAdmin):
base_model = ModelC base_model = ModelC # Explicitly set here!
show_in_index = True # makes child model admin visible in main admin site show_in_index = True # makes child model admin visible in main admin site
# define custom features here # define custom features here
@ -89,7 +89,7 @@ The models are taken from :ref:`advanced-features`.
@admin.register(ModelA) @admin.register(ModelA)
class ModelAParentAdmin(PolymorphicParentModelAdmin): class ModelAParentAdmin(PolymorphicParentModelAdmin):
""" The parent model admin """ """ The parent model admin """
base_model = ModelA base_model = ModelA # Optional, explicitly set here.
child_models = (ModelB, ModelC) child_models = (ModelB, ModelC)
list_filter = (PolymorphicChildModelFilter,) # This is optional. list_filter = (PolymorphicChildModelFilter,) # This is optional.

View File

@ -69,7 +69,7 @@ The admin :ref:`admin example <admin-example>` becomes:
class ModelAChildAdmin(PolymorphicChildModelAdmin, VersionAdmin): class ModelAChildAdmin(PolymorphicChildModelAdmin, VersionAdmin):
base_model = ModelA base_model = ModelA # optional, explicitly set here.
base_form = ... base_form = ...
base_fieldsets = ( base_fieldsets = (
... ...
@ -83,7 +83,7 @@ The admin :ref:`admin example <admin-example>` becomes:
class ModelAParentAdmin(VersionAdmin, PolymorphicParentModelAdmin): class ModelAParentAdmin(VersionAdmin, PolymorphicParentModelAdmin):
base_model = ModelA base_model = ModelA # optional, explicitly set here.
child_models = ( child_models = (
(ModelB, ModelBAdmin), (ModelB, ModelBAdmin),
(ModelC, ModelCAdmin), (ModelC, ModelCAdmin),

View File

@ -4,13 +4,13 @@ from pexp.models import *
class ProjectAdmin(PolymorphicParentModelAdmin): class ProjectAdmin(PolymorphicParentModelAdmin):
base_model = Project base_model = Project # Can be set explicitly.
list_filter = (PolymorphicChildModelFilter,) list_filter = (PolymorphicChildModelFilter,)
child_models = (Project, ArtProject, ResearchProject) child_models = (Project, ArtProject, ResearchProject)
class ProjectChildAdmin(PolymorphicChildModelAdmin): class ProjectChildAdmin(PolymorphicChildModelAdmin):
base_model = Project base_model = Project # Can be set explicitly.
# On purpose, only have the shared fields here. # On purpose, only have the shared fields here.
# The fields of the derived model should still be displayed. # The fields of the derived model should still be displayed.
@ -27,13 +27,12 @@ admin.site.register(ResearchProject, ProjectChildAdmin)
class UUIDModelAAdmin(PolymorphicParentModelAdmin): class UUIDModelAAdmin(PolymorphicParentModelAdmin):
base_model = UUIDModelA
list_filter = (PolymorphicChildModelFilter,) list_filter = (PolymorphicChildModelFilter,)
child_models = (UUIDModelA, UUIDModelB) child_models = (UUIDModelA, UUIDModelB)
class UUIDModelAChildAdmin(PolymorphicChildModelAdmin): class UUIDModelAChildAdmin(PolymorphicChildModelAdmin):
base_model = UUIDModelA pass
admin.site.register(UUIDModelA, UUIDModelAAdmin) admin.site.register(UUIDModelA, UUIDModelAAdmin)
@ -42,13 +41,12 @@ admin.site.register(UUIDModelC, UUIDModelAChildAdmin)
class ProxyAdmin(PolymorphicParentModelAdmin): class ProxyAdmin(PolymorphicParentModelAdmin):
base_model = ProxyBase
list_filter = (PolymorphicChildModelFilter,) list_filter = (PolymorphicChildModelFilter,)
child_models = (ProxyA, ProxyB) child_models = (ProxyA, ProxyB)
class ProxyChildAdmin(PolymorphicChildModelAdmin): class ProxyChildAdmin(PolymorphicChildModelAdmin):
base_model = ProxyBase pass
admin.site.register(ProxyBase, ProxyAdmin) admin.site.register(ProxyBase, ProxyAdmin)

View File

@ -8,6 +8,7 @@ from django.urls import resolve
from django.utils import six from django.utils import six
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from polymorphic.utils import get_base_polymorphic_model
from ..admin import PolymorphicParentModelAdmin from ..admin import PolymorphicParentModelAdmin
@ -25,8 +26,6 @@ class PolymorphicChildModelAdmin(admin.ModelAdmin):
* It adds the base model to the template lookup paths. * It adds the base model to the template lookup paths.
* It allows to set ``base_form`` so the derived class will automatically include other fields in the form. * 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. * It allows to set ``base_fieldsets`` so the derived class will automatically display any extra fields.
The ``base_model`` attribute must be set.
""" """
base_model = None base_model = None
base_form = None base_form = None
@ -34,6 +33,12 @@ class PolymorphicChildModelAdmin(admin.ModelAdmin):
extra_fieldset_title = _("Contents") # Default title for extra fieldset extra_fieldset_title = _("Contents") # Default title for extra fieldset
show_in_index = False show_in_index = False
def __init__(self, model, admin_site, *args, **kwargs):
super(PolymorphicChildModelAdmin, self).__init__(model, admin_site, *args, **kwargs)
if self.base_model is None:
self.base_model = get_base_polymorphic_model(model)
def get_form(self, request, obj=None, **kwargs): def get_form(self, request, obj=None, **kwargs):
# The django admin validation requires the form to have a 'class Meta: model = ..' # The django admin validation requires the form to have a 'class Meta: model = ..'
# attribute, or it will complain that the fields are missing. # attribute, or it will complain that the fields are missing.

View File

@ -18,6 +18,7 @@ from django.utils.http import urlencode
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from polymorphic.utils import get_base_polymorphic_model
from .forms import PolymorphicModelChoiceForm from .forms import PolymorphicModelChoiceForm
@ -36,9 +37,8 @@ class ChildAdminNotRegistered(RuntimeError):
class PolymorphicParentModelAdmin(admin.ModelAdmin): class PolymorphicParentModelAdmin(admin.ModelAdmin):
""" """
A admin interface that can displays different change/delete pages, depending on the polymorphic model. A admin interface that can displays different change/delete pages, depending on the polymorphic model.
To use this class, two variables need to be defined: To use this class, one attribute need to be defined:
* :attr:`base_model` should
* :attr:`child_models` should be a list of (Model, Admin) tuples * :attr:`child_models` should be a list of (Model, Admin) tuples
Alternatively, the following methods can be implemented: Alternatively, the following methods can be implemented:
@ -50,7 +50,7 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
The derived models should *not* register the ModelAdmin, but instead it should be returned by :func:`get_child_models`. The derived models should *not* register the ModelAdmin, but instead it should be returned by :func:`get_child_models`.
""" """
#: The base model that the class uses #: The base model that the class uses (auto-detected if not set explicitly)
base_model = None base_model = None
#: The child models that should be displayed #: The child models that should be displayed
@ -71,6 +71,9 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
super(PolymorphicParentModelAdmin, self).__init__(model, admin_site, *args, **kwargs) super(PolymorphicParentModelAdmin, self).__init__(model, admin_site, *args, **kwargs)
self._is_setup = False self._is_setup = False
if self.base_model is None:
self.base_model = get_base_polymorphic_model(model)
def _lazy_setup(self): def _lazy_setup(self):
if self._is_setup: if self._is_setup:
return return