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)
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
.
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.
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With