question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Correct way to implement a cancel button w/ UpdateView+ModelForm?

See original GitHub issue

Just wanted to run this by you and get your thoughts…

If you’re using ModelForms and UpdateView, you’re letting Django take care of the form layout, tweaking some setting perhaps via Crispy, and then letting Crispy render it.

In these types of views, you often want to have a Cancel button on your form:

pastedgraphic-1

If you Google around, end users of Crispy don’t seem to have a consistent idea of how to accomplish this. ** Some people suggest appending raw HTML via Crispy’s helper object – not a clean approach ** Some people suggest just using Crispy to render the fields, then wrap your own form in HTML – not clean either, since now you’ve got to maintain code in two places ** Some people suggest putting a button in which has onclick=“history.go(-1)” – go back a page in the browser history. The history(-1) approach is bad if you submit with bad data, which posts and comes back invalid, and then try to cancel – in this case, going back one page takes you back to the form you submitted with invalid data.

(As an aside, Django is supposed to be Javascript-agnostic, meaning that if you’ve got to resort to DOM manipulation via Javascript to accomplish something this basic, you’re probably doing something wrong.)

I had an idea - perhaps you could add another Submit button, this time labeled “Cancel”, and style it accordingly.

basically, taking this:

        self.helper.add_input(Submit('submit', 'Create Project'))

and making it this:

        self.helper.add_input(Submit('submit', 'Create Project'))
        self.helper.add_input(Submit('cancel', 'Cancel', css_class='btn-default'))

(The styling on the Cancel button was supposed to give me a basic black button as appears in my picture above.)

Since these are both form submits which do a post back to the view, your view code would look something like this.

def form_valid(self, form):
    if 'cancel' in self.request.POST:
        return HttpResponseRedirect(self.get_success_url())
    return super(Project_UpdateView, self).form_valid(form)

Basically, seeing if ‘cancel’ is in the POST dictionary and redirecting accordingly, otherwise following the normal path. It ends up functioning, but I noticed that I had very little control over the styling of that new Cancel button. If I styled it “btn-danger” (i.e. Red button), that worked. Otherwise, it always seemed to end up Blue like the other button.

pastedgraphic-2

So I looked into the Submit class within Crispy and found this:

input_type = 'submit'
field_classes = 'submit submitButton' if TEMPLATE_PACK == 'uni_form' else 'btn btn-primary'

What this means is that if you’re using bootstrap it’s always going to get styled the same way (‘btn-primary’, i.e. Blue button). Due to how bootstrap works, the Red danger button overrides this style, but things like Default button don’t.

My solution:

create a new SubmitButton class which removes the “btn-primary” styling.

from django.conf import settings TEMPLATE_PACK = getattr(settings, ‘CRISPY_TEMPLATE_PACK’, ‘bootstrap’) class SubmitButton(BaseInput): input_type = ‘submit’ field_classes = ‘button’ if TEMPLATE_PACK == ‘uni_form’ else ‘btn’ #removed btn-primary

When you use it, you’ve got to specify the style of the button, since the “btn-primary” default is gone now. So now, when you use it in Crispy layout code, it’s clean and simple and you now have control over the styling of your buttons.

self.helper.add_input(SubmitButton('submit', 'Update',css_class='btn-primary'))
self.helper.add_input(SubmitButton('cancel', 'Cancel',css_class='btn btn-default'))

and the rendered HTML is correct:

 <div class="form-actions">
  <input type="submit" name="submit" value="Update" class="btn btn-primary" id="submit-id-submit">
  <input type="submit" name="cancel" value="Cancel" class="btn btn-default" id="submit-id-cancel"> 
 </div>

There’s probably a better solution which would involve adding an anchor, which is either styled like a button or wraps a button, and links back to the page which invoked the UpdateView in the first place. The anchor approach would mean one less transaction (the POST) to handle the Cancel operation.

Issue Analytics

  • State:closed
  • Created 10 years ago
  • Comments:9

github_iconTop GitHub Comments

2reactions
carltongibsoncommented, Jan 27, 2017

Please don’t make “+1” comments. There’s a reaction button for that purpose. It just wastes time and is annoying

1reaction
diogolrcommented, Feb 20, 2017

If you’re using Bootstrap (like I think you do), you can use FormActions:

from crispy_forms.bootstrap import FormActions
from crispy_forms.layout import Button
from crispy_forms.layout import Submit

helper.add_layout(
    Layout(
        Field( ... ),
        Field( ... ),
        Field( ... ),
        FormActions(
            Submit( 'save', 'Save', css_class = 'btn btn-primary' ),
            Button( 'cancel', 'Cancel', css_class = 'btn btn-default' )
        )
    )
)
Read more comments on GitHub >

github_iconTop Results From Across the Web

Adding a Cancel button in Django class-based views, ...
This a simple approach to add a Cancel button to any form or generic view in Django that uses its class-based views.
Read more >
Creating cancel button on UpdateView form - django
I want to create a Cancel button ...
Read more >
Form handling with class-based views
Model form views provide a form_valid() implementation that saves the model ... for CreateView or UpdateView - they will use get_absolute_url() on the...
Read more >
Create Update & Delete (CRUD) with Model Forms - YouTube
Checkout my new Django Course!https://dennisivy.teachable.com/p/django-beginners-courseCRUD operations with Django model forms.
Read more >
Django Tutorial Part 9: Working with forms - MDN Web Docs
Developers need to write HTML for the form, validate and properly ... few of the ways you can create and work with forms,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found