I'm rather new to Django and I'm using Django 1.0.
I have this:
forms.py:
class MyForm(forms.Form):
extra_cheeze = forms.BooleanField(required=False,
initial=False,
label='Extra cheeze')
views.py:
def order_something(request):
form = MyForm(request.POST or None)
if request.method == 'POST' and form.is_valid():
# do stuff...
The problem is that the form is not valid unless the checkbox is checked, so there doesn't seem to be a way to get a False value from the field. As far as I can understand from the docs, it should work. It works if I add a CharField to my form...
Am I misunderstanding something here or is this a bug? (Yes, I have googled but found nothing relevant)
Update: As suggested by @Dominic Rodger, I tried adding a hidden field
dummy = forms.CharField(initial='dummy', widget=forms.widgets.HiddenInput())
and that makes the form valid. This workaround enables me to move on right now, but it would still be interesting to know if I'm misunderstanding something...
There was a bug in the code in my question. Thanks to @d0ugal for helping me spot it by including a slightly different example. The problem was here:
The bug was that I assumed that request.POST would evaluate to True if it was a post. But since browsers don't post anything for a not-checked checkbox, and that was the only field, the POST data was an empty dictionary, which evaluates to False. This caused None to be used as initialization data, causing the form to be unbound and not valid.
@d0ugal's example does the safe thing and tests request.method first.
This also works for me on 1.1, 1.0.3 and 1.0 (I have these three Virtual environments setup). I only tested this in FireFox so if its a browser issue thats another matter but as far as I know they all handle POST data with checkboxes the same.
Here is the full code for the project so you can reproduce at your leisure and compare with yours to see the difference.
Setting up in Ubuntu
Then in the myfirst app folder;
/myfirst/views.py
/myfirst/forms.py from django import forms
/myfirst/templates/test.html
/urls.py from django.conf.urls.defaults import *
Then just run the project $ python manage.py runserver and browse to http://localhost:8000/. You'll actually find that required doesn't do anything with the checkbox, since you can't leave it blank - a 'blank' answer is effectively 'no'. If you want to make sure a user selects an answer have a multiple choice where the user has to select yes or no. You could force them to answer with radio buttons too.