Have multiple submit buttons for the same Django form

Django form with two submit buttons
Image: Django form with two submit buttons (License: CC-BY-SA Marcelo Canina)

Behave differently depending on which button the user clicks

Published:

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

Uruguay
Marcelo Canina
I'm Marcelo Canina, a developer from Uruguay. I build websites and web-based applications from the ground up and share what I learn here.
comments powered by Disqus

How to have more than one submit button with different behaviour attached to the same form in Django.

Clutter-free software concepts.
Translations English Español

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

·