Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 16 additions & 20 deletions src/polymorphic/admin/childadmin.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,26 +160,22 @@ def _get_parent_admin(self):
# when parent_model is in among child_models, just return super instance
return super()

try:
return self.admin_site._registry[parent_model]
except KeyError:
# Admin is not registered for polymorphic_ctype model, but perhaps it's registered
# for a intermediate proxy model, between the parent_model and this model.
for klass in inspect.getmro(self.model):
if not issubclass(klass, parent_model):
continue # e.g. found a mixin.

# Fetch admin instance for model class, see if it's a possible candidate.
model_admin = self.admin_site._registry.get(klass)
if model_admin is not None and isinstance(
model_admin, PolymorphicParentModelAdmin
):
return model_admin # Success!

# If we get this far without returning there is no admin available
raise ParentAdminNotRegistered(
f"No parent admin was registered for a '{parent_model}' model."
)
# Only PolymorphicParentModelAdmin registrations are considered, whether
# they are for the polymorphic root model or an intermediate proxy/model
# between the parent_model and this model.
for klass in inspect.getmro(self.model):
if not issubclass(klass, parent_model):
continue # e.g. found a mixin.

# Fetch admin instance for model class, see if it's a possible candidate.
model_admin = self.admin_site._registry.get(klass)
if model_admin is not None and isinstance(model_admin, PolymorphicParentModelAdmin):
return model_admin # Success!

# If we get this far without returning there is no admin available
raise ParentAdminNotRegistered(
f"No parent admin was registered for a '{parent_model}' model."
)

def response_post_save_add(self, request, obj):
return self._get_parent_admin().response_post_save_add(request, obj)
Expand Down
22 changes: 22 additions & 0 deletions src/polymorphic/tests/test_admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1629,6 +1629,28 @@ class Model2CAdmin(PolymorphicChildModelAdmin):
parent = c_admin._get_parent_admin()
assert isinstance(parent, PolymorphicParentModelAdmin)

def test_child_admin_get_parent_admin_skips_regular_root_admin(self):
"""_get_parent_admin() ignores a registered root ModelAdmin when finding the polymorphic parent."""

@self.register(Model2A)
class Model2ARootAdmin(admin.ModelAdmin):
pass

@self.register(Model2B)
class Model2BParentAdmin(PolymorphicParentModelAdmin):
base_model = Model2B
child_models = (Model2C,)

@self.register(Model2C)
class Model2CAdmin(PolymorphicChildModelAdmin):
base_model = Model2B

c_admin = self.get_admin_instance(Model2C)
parent = c_admin._get_parent_admin()

assert parent is self.get_admin_instance(Model2B)
assert parent is not self.get_admin_instance(Model2A)

def test_child_admin_get_parent_admin_not_registered(self):
"""_get_parent_admin() raises ParentAdminNotRegistered when MRO has no parent admin."""
from polymorphic.admin.childadmin import ParentAdminNotRegistered
Expand Down
Loading