Skip to content

PolymorphicChildModelAdmin redirects to the root model list view instead of the first PolymorphicParentModelAdminΒ #863

@olivierdalang

Description

@olivierdalang

Hey !

It seems PolymorphicChildModelAdmin's logic to pick where to redirect after saving a form has a flaw.

In my case, the root model is registeredto the admin (as a regular ModelAdmin, not a PolymorphicParentModelAdmin) only because I need it for autocomplete. I do have an actual PolymorphicParentModelAdmin that represents the parent I want to see in the admin which is for a subclass (so not the root).

As far as I understand, the issue is in PolymorphicChildModelAdmin._get_parent_admin, where before trying to move up the MRO to find the first PolymorphicParentModelAdmin, it checks if the root model is registered in the admin, and if so, returns the root model admin early.

I think we can fix this by removing self.admin_site._registry[parent_model] below (and the try...except around it).

What do you think ? Would that be reasonably backwards compatible ?

Happy to open a pull request but since it's my first contribution here I prefer to ask before putting work in this.

Cheers

class PolymorphicChildModelAdmin(_ModelAdminBase, Generic[_ModelT]):

    def _get_parent_admin(self):
        # this returns parent admin instance on which to call response_post_save methods
        parent_model = self.model._meta.get_field("polymorphic_ctype").model
        if parent_model == self.model:
            # when parent_model is in among child_models, just return super instance
            return super()

        try:
            return self.admin_site._registry[parent_model]  # πŸ”΄πŸ”΄πŸ”΄ DELETE THIS LINE  πŸ”΄πŸ”΄πŸ”΄ 
        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."
            )

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions