Improve #215 to handle cases where the real_admin points back to self.

When the base model also serves as child model, the flow no longer
points to the child admin, but returns `self` instead. Either every user
of `_get_real_admin()` should detect this, or we return the super method
as convenience.
fix_request_path_info
Diederik van der Boor 2016-06-13 10:53:29 +02:00
parent b75e55b6f1
commit c1ee5aad0b
1 changed files with 11 additions and 6 deletions

View File

@ -167,15 +167,15 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
choices.append((ct.id, model._meta.verbose_name)) choices.append((ct.id, model._meta.verbose_name))
return choices return choices
def _get_real_admin(self, object_id): def _get_real_admin(self, object_id, super_if_self=True):
try: try:
obj = self.model.objects.non_polymorphic() \ obj = self.model.objects.non_polymorphic() \
.values('polymorphic_ctype').get(pk=object_id) .values('polymorphic_ctype').get(pk=object_id)
except self.model.DoesNotExist: except self.model.DoesNotExist:
raise Http404 raise Http404
return self._get_real_admin_by_ct(obj['polymorphic_ctype']) return self._get_real_admin_by_ct(obj['polymorphic_ctype'], super_if_self=super_if_self)
def _get_real_admin_by_ct(self, ct_id): def _get_real_admin_by_ct(self, ct_id, super_if_self=True):
try: try:
ct = ContentType.objects.get_for_id(ct_id) ct = ContentType.objects.get_for_id(ct_id)
except ContentType.DoesNotExist as e: except ContentType.DoesNotExist as e:
@ -185,9 +185,9 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
if not model_class: if not model_class:
raise Http404("No model found for '{0}.{1}'.".format(*ct.natural_key())) # Handle model deletion raise Http404("No model found for '{0}.{1}'.".format(*ct.natural_key())) # Handle model deletion
return self._get_real_admin_by_model(model_class) return self._get_real_admin_by_model(model_class, super_if_self=super_if_self)
def _get_real_admin_by_model(self, model_class): def _get_real_admin_by_model(self, model_class, super_if_self=True):
# In case of a ?ct_id=### parameter, the view is already checked for permissions. # In case of a ?ct_id=### parameter, the view is already checked for permissions.
# Hence, make sure this is a derived object, or risk exposing other admin interfaces. # Hence, make sure this is a derived object, or risk exposing other admin interfaces.
if model_class not in self._child_models: if model_class not in self._child_models:
@ -196,10 +196,15 @@ class PolymorphicParentModelAdmin(admin.ModelAdmin):
try: try:
# HACK: the only way to get the instance of an model admin, # HACK: the only way to get the instance of an model admin,
# is to read the registry of the AdminSite. # is to read the registry of the AdminSite.
return self._child_admin_site._registry[model_class] real_admin = self._child_admin_site._registry[model_class]
except KeyError: except KeyError:
raise ChildAdminNotRegistered("No child admin site was registered for a '{0}' model.".format(model_class)) raise ChildAdminNotRegistered("No child admin site was registered for a '{0}' model.".format(model_class))
if super_if_self and real_admin is self:
return super(PolymorphicParentModelAdmin, self)
else:
return real_admin
def get_queryset(self, request): def get_queryset(self, request):
# optimize the list display. # optimize the list display.
qs = super(PolymorphicParentModelAdmin, self).get_queryset(request) qs = super(PolymorphicParentModelAdmin, self).get_queryset(request)