Adding a Cancel button in Django class-based views, editing views and forms

Save and Cancel Bootstrap 4 buttons in Django
Image: Save and Cancel Bootstrap 4 buttons in Django (License: CC-SA-BY Marcelo Canina)

A simple approach to go back from a template

Published:
Last modified:
Tag Django

Overview

This a simple approach to add a Cancel button to any form or generic view in Django that uses its class-based views.

Context view

In Django there is a special mixin django.views.generic.base.ContextMixin used by most class-based view, which is responsible of including the keyword arguments into the template context. But it also includes the proper view in the process in the variable view like kwargs.setdefault('view', self) as showed in its source code.

class ContextMixin:
    """
    A default context mixin that passes the keyword arguments received by
    get_context_data() as the template context.
    """
    extra_context = None

    def get_context_data(self, **kwargs):
        kwargs.setdefault('view', self)
        if self.extra_context is not None:
            kwargs.update(self.extra_context)
        return kwargs

ContentMixins are used by all of the generic editing views:

  • django.views.generic.edit.
    • FormView,
    • CreateView,
    • UpdateView,
    • DeleteView

So we are sure we have the view in our template context.

The above view will contain the URL used to redirect after a successful form submission, available at view.get_success_url, so we use that in a Cancel link button like <a href="{{ view.get_success_url }}" class="btn btn-secondary">Cancel</a>.

In our template:

    <form method="post">{% csrf_token %}
	....
	<input class="btn btn-success" type="submit" value="Save" />
	<a href="{{ view.get_success_url }}" class="btn btn-secondary">Cancel</a>
    </form>

Special cases

Sometimes your success_url will be expecting some parameters as for a newly created item, specially in CreateView’s, for example:

class EquilangCreatePersonalView(CreateView):
    def get_success_url(self):
        """ Redirects to the newly created object """
        new = self.object
        url = reverse_lazy("my-item", kwargs={"pk": new.pk})
        return url

In this case we can’t rely on it for the cancel URL, so we just use javascript to get back to the previous page:

<button class="btn btn-link" onclick="javascript:history.back();">Cancel</button>

Explanation

Any HTML element has event handler content attributes, in this case we have the HTML button element and we use the onclick event hander to detect when a user clicks it.

Then we use the javascript History interface.

The History interface allows manipulation of the browser session history, that is the pages visited in the tab or frame that the current page is loaded in.

Specifically the back method.

This asynchronous method goes to the previous page in session history, the same action as when the user clicks the browser's Back button. Equivalent to history.go(-1).

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 add a Cancel button in a Django template without javascript.

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

·