Have multiple submit buttons for the same Django form
Behave differently depending on which button the user clicks
Overview
Guide to add multiple submit buttons to a form and attach a different behaviour to each of them using Django’s Class Based Views.
Explanation
For this example we will use a typical Django form template looking like:
<form method="post">{% csrf_token %}
{{ form }}
<input class="btn btn-primary" type="submit" value="Save" />
</form>
Using this CBV:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView
from models import MyModel
class MyView(LoginRequiredMixin, CreateView):
"""
A view that displays a form for creating an object, redisplaying the form with validation errors (if there are any) and saving the object.
"""
model = MyModel
So we will add another submit button displaying the text: Save and add text in addition to the already showed Save button that redirects to another page.
Process
1. Adding the button
We will focus our attention in the form’s input element.
The input element represents a button that, when activated, submits the form. If the element has a value attribute, the button’s label must be the value of that attribute
Using its name attribute to differentiate it from other input buttons.
The name content attribute gives the name of the form control, as used in §4.10.21 Form submission and in the form element’s elements object. If the attribute is specified, its value must not be the empty string.
In our template, we add an input element with name="add_text"
:
<input class="btn btn-primary" type="submit" value="Save" />
<input class="btn btn-primary" type="submit" name="add_text" value="Save and add text" />
2. Processing the form
The key to process the form and know which button the user used, is to use the get_success_url() function to adjust the behaviour we want.
Any CBV that inherits from django.views.generic.edit.FormMixin
will
have it like CreateView
, UpdateView
and DeleteView
.
Then the submit button used will be in the self.request.POST variable which will be a QueryDict object containing the above button name.
A dictionary-like object containing all given HTTP POST parameters, providing that the request contains form data.
So it will contain something like:
QueryDict: {'csrfmiddlewaretoken':
['crvObJ2k8jRClFX9vr6ZmNiDCtaMAzM6a148BxobrfoHaJGhFxs3pQDxS4F7XXX'],
'title': ['Example Foo Bar'], 'add_text': ['Save and add text']}
And we can check if the submit name value is present in the above dictionary.
Putting it all together in the view:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.views.generic import CreateView
from models import MyModel
class MyView(LoginRequiredMixin, CreateView):
"""
A view that displays a form for creating an object, redisplaying the form with validation errors (if there are any) and saving the object.
"""
model = MyModel
def get_success_url(self):
"""Detect the submit button used and act accordingly"""
if 'add_text' in self.request.POST:
url = reverse_lazy('add-text')
else:
url = reverse_lazy('model-detail', kwargs={
//...
})
return url
References
- https://docs.djangoproject.com/en/2.2/topics/class-based-views/
- https://docs.djangoproject.com/en/2.0/ref/class-based-views/generic-editing/#createview
- August 1, 2023
- How to create a reusable Django app and distribute it with PIP or publish to pypi.orgJune 29, 2021
- How To Serve Multiple Django Applications with uWSGI and Nginx in Ubuntu 20.04October 26, 2020
- How to add favicon to Django in 4 stepsSeptember 3, 2020
- Categories in Django with BreadcrumbsAugust 30, 2020
- How To Migrate From SQLite To PostgreSQL In Django In 3 stepsAugust 28, 2020
- Practical guide to internationalize a Django app in 5 steps.August 24, 2020
- Disable new users singup when using Django's allauth packageSeptember 3, 2019
- How to add ads.txt to Django as requested by Google AdsenseAugust 30, 2019
- Have multiple submit buttons for the same Django form
- Better Testing with Page Object Design in DjangoMay 1, 2019
- Generating slugs automatically in Django without packages - Two easy and solid approachesFebruary 14, 2019
- How to set up Django tests to use a free PostgreSQL database in HerokuFebruary 13, 2019
- Dynamically adding forms to a Django FormSet with an add button using jQueryFebruary 6, 2019
- Use of Django's static templatetag in css file to set a background imageFebruary 1, 2019
- Activate Django's manage.py commands completion in Bash in 2 stepsJanuary 29, 2019
- Sending Emails with Django using SendGrid in 3 easy stepsJanuary 9, 2019
- Adding Users to Your Django Project With A Custom User ModelSeptember 21, 2018
- Setting Up A Factory For One To Many Relationships In FactoryboyApril 17, 2018
- Generate UML class diagrams from django modelsMarch 24, 2018
- Set Up Ubuntu To Serve A Django Website Step By StepJuly 3, 2017
- Django Project Directory StructureJuly 16, 2016
- How to Have Different Django Settings for Development and Production, and environment isolationJune 10, 2016
- Django OverviewJune 2, 2016
Django Forms
- Adding a Cancel button in Django class-based views, editing views and formsJuly 15, 2019
- Using Django Model Primary Key in Custom Forms THE RIGHT WAYJuly 13, 2019
- Django formset handling with class based views, custom errors and validationJuly 4, 2019
- How To Use Bootstrap 4 In Django FormsMay 25, 2018
- Understanding Django FormsApril 30, 2018
- How To Create A Form In DjangoJuly 29, 2016
Articles
Subcategories
Except as otherwise noted, the content of this page is licensed under CC BY-NC-ND 4.0 . Terms and Policy.
Powered by SimpleIT Hugo Theme
·