Django Admin changelist submit redirect

Viewed 42

Is it possible to have django redirect to another page after submitting changes directly in the changelist view? (After specifying the list_editable fields)

Already tried with different methods response_post_save_change, response_change or response_add but none of them worked.

I suspect it may be within the changelist_view, not sure how to tackle it since it handles the form saving.

1 Answers

You are correct, you'll need to override the changelist_view method in your admin class. That method returns a response-like object, and it's definitely possible to customize that value.

Approach #1: copy the entire ModelAdmin.changelist_view method into your own admin class, and then modify it to meet your needs. Probably the safest bet for your situation, even if you're only changing one single line of code in this method (which is 99 lines long at this moment).

class MyAdmin(admin.ModelAdmin):
    @csrf_protect_m
    def changelist_view(self, request, extra_context=None):
        """
        The 'change list' admin view for this model.
        """
        ... omitting code that leads up to line 1756 (v3.2)  ...

        # Handle POSTed bulk-edit data.
        if request.method == 'POST' and cl.list_editable and '_save' in request.POST:
            ... omitting more code ...
            # This is it. Line 1785: change this to meet your needs
            return HttpResponseRedirect(request.get_full_path())

        ... omitting the rest of the code after this line ...
    

Approach #2: call it via super(), and then inspect/alter the results. This could potentially be unreliable (comments in the code), but here's what it would look like:

class MyAdmin(admin.ModelAdmin):
    def changelist_view(self, request, extra_context=None):
        request_full_path = request.get_full_path()
        response = super().changelist_view(request, extra_context)
        # This is not a foolproof condition! In the changelist_view method, you can
        # see that it returns this redirect in the following scenarios:
        # - if action_failed (line ~1745 in django.contrib.admin.options, v3.2)
        # - successful bulk update of the changelist (this is the use case you're targeting)
        if isinstance(response, HttpResponseRedirect) and response.location == request_full_path:
            # do something here, like return a redirect to a different URL
            return HttpResponseRedirect(reverse('my_url_name'))

        return response

So I'm not sure how you would determine which of the two conditions caused it to return the HttpResponseRedirect object with the exact same parameters (same status_code and same location) - one is a submission failure, the other is submission success! But you might have some manner of doing so within your application, so I'll leave it at that.

I would choose approach #1 myself, although I definitely dislike the amount of code that has to be copied into your own codebase, and having to maintain it / think about it in the future. But that's probably the best way.

Related