Django admin "save and view on site" button

Question:

The Django admin site is brilliant, and we use it a lot at my work. My question is this – how do I add an additional button at the bottom, along side the ‘save’, ‘save and continue editing’ etc buttons, that saves the model and then redirects to the ‘view on site’ button that is available at the top right of the form for models that have that defined?

Thanks in advance!

Asked By: Ben

||

Answers:

Besides adding button in change_form template, you would want to override response_change method of ModelAdmin (and response_add).

Something like this should work:

def response_change(self, request, obj):
  res = super(MyModelAdmin, self).response_change(request, obj)
  if "_preview" in request.POST:
    return HttpResponseRedirect('preview-url-here')
  else:
    return res
Answered By: bmihelac

To do this but also have the choice to show/hide it for certain model forms, here is what I did:

1. First override the submit_line.html template by creating a custom one under the main templates folder: my_project/templates/admin/submit_line.html, copy the content from the original one and add the custom button to submit-row block (it won’t be displayed by default since it’s set to False):

# submit_line.html

{% load i18n admin_urls %}
<div class="submit-row">
{% block submit-row %}
{% if show_save %}<input type="submit" value="{% trans 'Save' %}" class="default" name="_save">{% endif %}
...
...
...
{% if show_save_and_preview|default:False %}<input type="submit" value="{% trans 'Save and preview' %}" name="_preview">{% endif %}
{% endblock %}
</div>


2. Next, to simply show it for certain models, just override your ModelAdmin methods:

changeform_view: to display the button on the template.

response_change: to set where it will redirect to after saving.

# admin.py

class MyModelAdmin(admin.ModelAdmin):
    # ..
    # ..

    def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
        extra_context = extra_context or {}
        extra_context['show_save_and_preview'] = True
        return super(MyModelAdmin, self).changeform_view(request, object_id, extra_context=extra_context)

    def response_change(self, request, obj):
        res = super(MyModelAdmin, self).response_change(request, obj)
        if "_preview" in request.POST:
            # used object's custom method "get_url()":
            return HttpResponseRedirect(obj.get_url())
        else:
            return res

Now it will be displayed for this particular form, to do the same for other models, just override the two methods above.

Answered By: Badjio

You can add a custom button to "Add" form and "Change" form for a specifc admin and redirect to "VIEW SITE" url after pressing a custom button.

First, about how to add a custom button to "Add" form and "Change" form for a specifc admin, see How to add a custom button at the bottom of "Add" form and "Change" form for a specifc admin or How to add a custom button right next to "SAVE" button on "Add" form and "Change" form for a specifc admin

Next, to redirect to "VIEW SITE" url after pressing a custom button on "Add" form and "Change" form, set "redirect(admin.site.site_url)" in "response_add()" and "response_change()" as shown below. *Whether or not setting "response_add()" and "response_change()", inputted data to fields is saved after pressing a custom button:

# "admin.py"

from django.contrib import admin
from .models import Person

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    change_form_template = "admin/custom_change_form.html"
    
    def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
        extra_context = extra_context or {}
        
        extra_context['custom_button'] = True
        
        return super().changeform_view(request, object_id, form_url, extra_context)

    def response_add(self, request, obj, post_url_continue=None):

        if "_custom_button" in request.POST:
            # Do something
            return redirect(admin.site.site_url) # Here
        else:
            # Do something
            return redirect(admin.site.site_url) # Here

    def response_change(self, request, obj):
        
        if "_custom_button" in request.POST:
            # Do something
            return redirect(admin.site.site_url) # Here
        else:
            # Do something
            return redirect(admin.site.site_url) # Here
Answered By: Kai – Kazuya Ito