Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a cancel button to DeleteView in django

What's the best way to add a "cancel" button to a generic class-based view in Django?

In the example below, I would like the cancel button to take you to success_url without deleting the object. I have tried adding a button <input type="submit" name="cancel" value="Cancel" /> to the template. I can detect if this button was pressed by overriding the post method of the AuthorDelete class, but I can't work out how to redirect from there.

Example myapp/views.py:

from django.views.generic.edit import DeleteView
from django.core.urlresolvers import reverse_lazy
from myapp.models import Author

class AuthorDelete(DeleteView):
    model = Author
    success_url = reverse_lazy('author-list')

    def post(self, request, *args, **kwargs):
        if request.POST["cancel"]:
            return ### return what? Can I redirect from here?
        else:
            return super(AuthorDelete, self).post(request, *args, **kwargs)

Example myapp/author_confirm_delete.html:

<form action="" method="post">{% csrf_token %}
    <p>Are you sure you want to delete "{{ object }}"?</p>
    <input type="submit" value="Confirm" />
    <input type="submit" name="cancel" value="Cancel" /> 
</form>

(Examples adapted from the docs)

like image 598
Michael Dunn Avatar asked Jul 16 '13 14:07

Michael Dunn


4 Answers

Your approach of overriding the post method and checking to see if the cancel button was pressed is ok. You can redirect by returning an HttpResponseRedirect instance.

from django.http import HttpResponseRedirect

class AuthorDelete(DeleteView):
    model = Author
    success_url = reverse_lazy('author-list')

    def post(self, request, *args, **kwargs):
        if "cancel" in request.POST:
            url = self.get_success_url()
            return HttpResponseRedirect(url)
        else:
            return super(AuthorDelete, self).post(request, *args, **kwargs)

I've used get_success_url() to be generic, its default implementation is to return self.success_url.

like image 114
Alasdair Avatar answered Oct 17 '22 10:10

Alasdair


Why don't you simply put a "Cancel" link to the success_url instead of a button? You can always style it with CSS to make it look like a button.

This has the advantage of not using the POST form for simple redirection, which can confuse search engines and breaks the Web model. Also, you don't need to modify the Python code.

like image 27
Berislav Lopac Avatar answered Oct 17 '22 11:10

Berislav Lopac


If using CBV's you can access the view directly from the template

<a href="{{ view.get_success_url }}" class="btn btn-default">Cancel</a>

Note: you should access it through the getter in case it has been subclassed.

This is noted in the ContextMixin docs

The template context of all class-based generic views include a view variable that points to the View instance.

like image 11
Inti Avatar answered Oct 17 '22 11:10

Inti


Having an element of type button, will not send a POST request. Therefore, you can use this to do a http redirection like this:

<button type="button" onclick="location.href='{{ BASE_URL }}replace-with-url-to-redirect-to/'">Cancel</button>
like image 1
theQuestionMan Avatar answered Oct 17 '22 10:10

theQuestionMan