Django form with BooleanField always invalid unless checked

djangodjango-forms

I have an application that uses the following form:

class ConfirmForm(forms.Form):
    account_name = forms.CharField(widget=forms.HiddenInput)
    up_to_date = forms.BooleanField(initial=True)

I use the form in the following template exerpt:

<form class="confirmform" action="/foo/" enctype="multipart/form-data" method="post">
{{ confirm_form.up_to_date }} Check if this data brings the account up to date.<br>
{{ confirm_form.account_name }} <input type="submit" name="confirm" value="Confirm" />
</form>

My view uses the following basic code structure:

if request.method == 'POST':
    #check for 'confirm' because I actually have multiple forms in this page
    if 'confirm' in request.POST:
        confirm_form = ConfirmForm(request.POST)
        if confirm_form.is_valid():
            #do stuff
        else:
            c['confirm_form'] = confirm_form
else:
    c['confirm_form'] = ConfirmForm({'account_name':'provided_value'})

Two things are wrong:

1) Even though I have initial=True, the checkbox is unchecked when the page loads

2) The form is always invalid unless I check the checkbox. It gives errors for up_to_date only: "This field is required."

I have read this similar question but his solution doesn't apply to my project.

So… what's going on?

Edit:

I updated the code above to be more faithful to my actual code.

Problem #1 was my fault because I was overriding the initial value by binding data when the form was instantiated.

Problem #2 I still consider an issue. Using required=False on up_to_date will fix the problem, however it doesn't seem correct that using the default widget, a BooleanField can be either NULL (causes validity check to fail) or True but never False.

Best Answer

In Django forms, Boolean fields must be created with required=False.

When the checkbox isn't checked, browsers do not send the field in the POST parameters of requests. Without specifying that the field is optional Django will treat it as a missing field when not in the POST parameters.

Imho it would be nice for Django to have this behavior by default for boolean form fields..

(this was already answered in comments by Yuji but it would be useful as an answer)

Related Topic