I'm using django 1.5.4
Here's a minimal example of the issue I'm facing.
The model:
#models.py
from django.db import models
class SampleModel(models.Model):
spam = models.BooleanField()
The form:
#forms.py
from django.forms import ModelForm
from .models import SampleModel
class SampleModelForm(ModelForm):
class Meta:
model = SampleModel
fields = ('spam', )
From the django shell:
>>> data = {} #intentionally blank
>>> form = SampleModelForm(data)
>>> is_valid = form.is_valid() #is_valid is True
>>> form.save() # model instance is created with "spam" set to False by default.
Am I validating the form incorrectly? form.is_valid
validates fields of other types correctly.
The docs indicate that all fields are required by default but is_valid
returns True
without the boolean field key being present.
I need to ensure that the boolean field is present in the input data.
As of now, I'm manually checking if the field is present and is of type bool
. Do you think I should override form.is_valid
and add this check so that it can be reused for other models too?
It turns out (from code inspection; the docs don't say) that model BooleanField
s have blank=True
set automatically in their __init__
method, thus making the automatically created model form field not required. This makes sense upon consideration (False counts as blank, so BooleanField
s need it to be true) but it's not obvious when you just read the docs.
If you want it to be required to be True
, the usual form field overrides apply - declare the field yourself or set its required
attribute to be True
somewhere before validating (I usually use the form's __init__
method). If you want it to allow True
or False
but not Python None
, it's harder.
Specifically, the standard widget for a BooleanField
is a checkbox. Browsers do not submit anything for unchecked checkboxes, so the checkbox widget treats the absence of the field from the submit as False
. There's no way to distinguish the user not selecting the checkbox from cases in which the input really is bad. You could use a different widget (say, a RadioSelect
) to at least make it possible for the browser to submit something for False
, but you still have the problem that the BooleanField
's to_python
method converts its value to a boolean
before validating, so you'd have to subclass and override.
Fortunately, False
is not considered empty by the validation code, so if you do that you'll be able to set required=True
and don't need custom cleaning methods.
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