required=True for BooleanFields

2,604 views
Skip to first unread message

Michael Blume

unread,
Jun 16, 2011, 3:14:38 PM6/16/11
to django-d...@googlegroups.com
In Django BooleanFields, the required flag is used to mean that the field must be checked for the form to validate. Required is True by default for all Fields, so this is the default behavior.

I strongly suspect that this violates principle of least surprise for most people including Boolean Fields in forms. It did for me.

I've patched it in my local Django checkout. I realize this is a backwards-incompatible change, so it might not be eligible for trunk any time soon, but FWIW, here's the patch:

--- i/django/forms/fields.py
+++ w/django/forms/fields.py
@@ -606,6 +606,11 @@ class URLField(CharField):
 class BooleanField(Field):
     widget = CheckboxInput
 
+    def __init__(self, *args, **kwargs):
+        if not args and 'required' not in kwargs:
+            kwargs['required'] = False
+        return super(BooleanField, self).__init__(*args, **kwargs)
+
     def to_python(self, value):
         """Returns a Python boolean object."""
         # Explicitly check for the string 'False', which is what a hidden field

Tai Lee

unread,
Jun 17, 2011, 12:34:12 AM6/17/11
to Django developers
This has been discussed many times in the past. For better or worse,
we're stuck with the current behaviour for backwards compatibility.

I personally think it's better this way. Without this behaviour, it
would be a PITA to implement forms that have a "required" boolean
field (must be ticked) without repeating yourself constantly by
writing custom validation for those fields. Most forms I work with
have a "Yes, I have agreed to the terms and conditions" or "Yes, I
want to receive emails from XYZ" type fields.

If your boolean fields are not "required" (as per the definition in
Django forms, "must be ticked"), why can't you just put
`required=False` in your form?

I'd try to avoid patching your local Django with a change like this
unless absolutely necessary so that you can cleanly upgrade and don't
end up writing code that does the opposite of what everyone else
expects.

Cheers.
Tai.

David Cramer

unread,
Jun 17, 2011, 1:41:15 AM6/17/11
to Django developers
I'm not suggesting changing the behavior (again due to the
compatibility concerns), but I completely agree with the original
poster(s).

Also, in my experience it's a much less common case that you're
wanting an "I agree" checkbox in your form, versus a "Boolean" field
which can be positive or negative.

Tai Lee

unread,
Jun 17, 2011, 2:00:48 AM6/17/11
to Django developers
On Jun 17, 3:41 pm, David Cramer <dcra...@gmail.com> wrote:
> I'm not suggesting changing the behavior (again due to the
> compatibility concerns), but I completely agree with the original
> poster(s).
>
> Also, in my experience it's a much less common case that you're
> wanting an "I agree" checkbox in your form, versus a "Boolean" field
> which can be positive or negative.

You can do that easily right now without changing Django by adding
`required=False` the BooleanField on your form. This is less
repetitive than writing the same validation method over and over
again.

def validate_somebooleanfield(self):
value = self.cleaned_data.get('somebooleanfield')
if not value:
raise forms.ValidationError('This field is required.')
return value

If this behaviour were to change, `required` would become a completely
meaningless argument to BooleanField because no value in the GET or
POST data is normalised to `False` because of the way checkbox values
are submitted in HTML forms.

The nature of boolean fields means that it's impossible to NOT provide
a value. NullBooleanField is used in those cases.

Cheers.
Tai.

Luke Plant

unread,
Jun 17, 2011, 5:57:34 AM6/17/11
to django-d...@googlegroups.com
On 17/06/11 07:00, Tai Lee wrote:

> If this behaviour were to change, `required` would become a completely
> meaningless argument to BooleanField because no value in the GET or
> POST data is normalised to `False` because of the way checkbox values
> are submitted in HTML forms.

The suggestion is not to change the behaviour of the 'required'
attribute, which has to work the way it does, for reasons you describe.
The suggestion is to change the default - so that this field, in
contrast to most (every?) other field, has 'required=False' by default.

Alternatively, you could define 'required' to be meaningless for check
boxes, and therefore ignored, since you cannot *not* return a value in
some way, and add another attribute like 'require_true' to get the
current behaviour. However, that would only be sensible if BooleanField
knows that it is using a check box widget, and other widgets are
possible that don't have this limitation e.g. two radio buttons with
neither initially selected.

So it is difficult to work out what behaviour is correct and consistent
here - the most obvious definition of 'required' (to me, anything) is
essentially meaningless for check boxes, the most common case, but not
for other widgets, yet it is an attribute of the field which is widget
agnostic.

Luke

--
LORENZ'S LAW OF MECHANICAL REPAIR:
After your hands become coated with grease, your nose will begin to
itch.

Luke Plant || http://lukeplant.me.uk/

Reply all
Reply to author
Forward
0 new messages