[Proposal] Making it easier to have "complicated" Admin Actions

So right now you can add simple admin actions “easily”:

@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
    ...
    actions = ["do_something"]

    @admin.action(description="Do A Thing")
    def do_something(self, request, queryset): ...

This is great for simple thing where you can just choose stuff. But the moment you need to collect more information than what instances to operate on, Django kinda bails on you, telling you stuff like “well pass the PKs as GET params to your own custom view and do stuff”.

Idea that I think makes sense: an AdminAction class that can do the following:

  • provide an action like the existing actions
  • optionally provide a form that, if present, is used for an intermediate view to collect more info before actually doing the action

For example:

class ExtraDataForm(Form):
    low_priority = BooleanField()

class DoThing(AdminAction):
    form_class = ExtraDataForm
    label = "Do Thing"
    url_slug = "do-thing"
    def perform_action(self, request, queryset, form):
         # only called if form.is_valid()
         if form.validated_data['low_priority']:
            ...
         else:
            ...

class TagAdmin(ModelAdmin):
    actions = [DoThing]

In the above example (roughly), when we pick the “Do Thing” action, we first get redirected to an intermediate view that shows us the form (and also has the admin submitted selections in a hidden form). Once submitting successfully there, we perform the action.

A “fluid” version of this would be for the form to actually appear in the admin list view directly, instead of on a separate page. For example, if you pick “Do Thing” in the action dropdown, it inline displays a form that needs to be filled out properly, right there.


^ imagine if in the above, under “Do A Thing” you just embedded a form.

This is mostly a sketch of an idea, but I do think it should be more straightforward to add a bit of extra data alongside admin actions.

2 Likes

Hmm.

You could put a form somewhere, I suppose, but how would you then display any extra instructions on the page? I am thinking a bit about the delete selected confirmation page, which displays some extra details and then you need to submit again. It seems like it might need a template with context as well. And then it gets more complex to handle every reasonable use.

I wonder if this could be implemented as a third party library first to try these ideas out?

1 Like

Regarding the “scope creep” meta-argument, class-based views have this vibe and handle it well.

Having something like AdminAction support something like the delete confirmation page is a very good way of looking at it. If Django needed that page, users need stuff like this.

A third-party lib is a good way to test out this idea though. Given how ModelAdmins can contribute URLs and the like, having one that handles a custom AdminAction thing.

I do think this sort of functionality should be in Django proper long-term. We can’t support everything, but “I need some parameters alongside an action” is the common case, not the exceptional case!

1 Like

I also felt the same limitation when it comes to admin actions, sometimes I needed a confirmation page and sometimes I needed to pass some values to it.

I created a package just for this.
https://pypi.org/project/django-admin-action-forms

It uses build in django forms and reuses templates from change form, it also supports filter_horizontal and autocomplete_fields. It should support most use cases, but I am open to suggestions.

I hope you find it useful. :slight_smile:

2 Likes