Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[1.5.x] Fixed #16820 -- Treated '0' value as True for checkbox inputs

Thanks Dan Fairs for the report and the initial patch.

Backport of be29329 from master.
  • Loading branch information...
commit fbb664066f8970279af020cf163cb364156290c3 1 parent 02b66f1
Claude Paroz authored October 26, 2012
2  django/forms/widgets.py
@@ -528,7 +528,7 @@ def value_from_datadict(self, data, files, name):
528 528
         values = {'true': True, 'false': False}
529 529
         if isinstance(value, six.string_types):
530 530
             value = values.get(value.lower(), value)
531  
-        return value
  531
+        return bool(value)
532 532
 
533 533
     def _has_changed(self, initial, data):
534 534
         # Sometimes data or initial could be None or '' which should be the
5  tests/regressiontests/forms/tests/forms.py
@@ -269,6 +269,11 @@ class SignupForm(Form):
269 269
         f = SignupForm({'email': 'test@example.com', 'get_spam': 'false'}, auto_id=False)
270 270
         self.assertHTMLEqual(str(f['get_spam']), '<input type="checkbox" name="get_spam" />')
271 271
 
  272
+        # A value of '0' should be interpreted as a True value (#16820)
  273
+        f = SignupForm({'email': 'test@example.com', 'get_spam': '0'})
  274
+        self.assertTrue(f.is_valid())
  275
+        self.assertTrue(f.cleaned_data.get('get_spam'))
  276
+
272 277
     def test_widget_output(self):
273 278
         # Any Field can have a Widget class passed to its constructor:
274 279
         class ContactForm(Form):
4  tests/regressiontests/forms/tests/widgets.py
@@ -225,6 +225,10 @@ def test_checkboxinput(self):
225 225
         # checkboxes).
226 226
         self.assertFalse(w.value_from_datadict({}, {}, 'testing'))
227 227
 
  228
+        value = w.value_from_datadict({'testing': '0'}, {}, 'testing')
  229
+        self.assertIsInstance(value, bool)
  230
+        self.assertTrue(value)
  231
+
228 232
         self.assertFalse(w._has_changed(None, None))
229 233
         self.assertFalse(w._has_changed(None, ''))
230 234
         self.assertFalse(w._has_changed('', None))

2 notes on commit fbb6640

Tim Graham
Owner

This is backwards incompatible in that I have the following code for an API which relies on the checkbox input returning the actual submitted value:

class BooleanChoiceField(forms.BooleanField):

    def clean(self, value):
         if value in (False, 'False', 'false', '0'):
            value = False
        elif value in (True, 'True', 'true', '1'):
            value = True
        else:
            raise ValidationError("Invalid choice '%s' for boolean field." % value)
        return value

Now value_from_datadict returns True for something like 'bad input'

Do you think I should rewrite my code with a different widget or should we made a change to Django itself?

Claude Paroz
Owner

Hi Tim,
Basically, I think that a BooleanField should return a boolean value. If you have a different specific need, I'd suggest you just subclass the form field and redefine clean(). Post on the ticket if you'd like some larger audience.

Please sign in to comment.
Something went wrong with that request. Please try again.