Reputation: 6767
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!
Upvotes: 6
Views: 4384
Reputation: 1
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
Upvotes: 0
Reputation: 760
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.
Upvotes: 2
Reputation: 6323
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
Upvotes: 8