瀏覽代碼

Fixed #9609 -- Modified the clean method of(Null)Boolean field to accept '1' and '0' as valid inputs. Thanks to psagers for the patch.

This is required to support the use of non-default form widgets such as RadioSelect when the data comes from MySQL, which uses 1/0 to represent booleans.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10660 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Russell Keith-Magee 16 年之前
父節點
當前提交
f6cca736a0
共有 2 個文件被更改,包括 31 次插入8 次删除
  1. 9 8
      django/forms/fields.py
  2. 22 0
      tests/regressiontests/forms/fields.py

+ 9 - 8
django/forms/fields.py

@@ -586,9 +586,10 @@ class BooleanField(Field):
     def clean(self, value):
         """Returns a Python boolean object."""
         # Explicitly check for the string 'False', which is what a hidden field
-        # will submit for False. Because bool("True") == True, we don't need to
-        # handle that explicitly.
-        if value == 'False':
+        # will submit for False. Also check for '0', since this is what
+        # RadioSelect will provide. Because bool("True") == bool('1') == True,
+        # we don't need to handle that explicitly.
+        if value in ('False', '0'):
             value = False
         else:
             value = bool(value)
@@ -607,13 +608,13 @@ class NullBooleanField(BooleanField):
     def clean(self, value):
         """
         Explicitly checks for the string 'True' and 'False', which is what a
-        hidden field will submit for True and False. Unlike the
-        Booleanfield we also need to check for True, because we are not using
-        the bool() function
+        hidden field will submit for True and False, and for '1' and '0', which
+        is what a RadioField will submit. Unlike the Booleanfield we need to
+        explicitly check for True, because we are not using the bool() function
         """
-        if value in (True, 'True'):
+        if value in (True, 'True', '1'):
             return True
-        elif value in (False, 'False'):
+        elif value in (False, 'False', '0'):
             return False
         else:
             return None

+ 22 - 0
tests/regressiontests/forms/fields.py

@@ -1077,6 +1077,10 @@ False
 True
 >>> f.clean(0)
 False
+>>> f.clean('1')
+True
+>>> f.clean('0')
+False
 >>> f.clean('Django rocks')
 True
 
@@ -1201,7 +1205,10 @@ True
 >>> f.clean(False)
 False
 >>> f.clean(None)
+>>> f.clean('0')
+False
 >>> f.clean('1')
+True
 >>> f.clean('2')
 >>> f.clean('3')
 >>> f.clean('hello')
@@ -1220,6 +1227,21 @@ True
 >>> f.cleaned_data['hidden_nullbool2']
 False
 
+# Make sure we're compatible with MySQL, which uses 0 and 1 for its boolean
+# values. (#9609)
+>>> NULLBOOL_CHOICES = (('1', 'Yes'), ('0', 'No'), ('', 'Unknown'))
+>>> class MySQLNullBooleanForm(Form):
+...     nullbool0 = NullBooleanField(widget=RadioSelect(choices=NULLBOOL_CHOICES))
+...     nullbool1 = NullBooleanField(widget=RadioSelect(choices=NULLBOOL_CHOICES))
+...     nullbool2 = NullBooleanField(widget=RadioSelect(choices=NULLBOOL_CHOICES))
+>>> f = MySQLNullBooleanForm({ 'nullbool0': '1', 'nullbool1': '0', 'nullbool2': '' })
+>>> f.full_clean()
+>>> f.cleaned_data['nullbool0']
+True
+>>> f.cleaned_data['nullbool1']
+False
+>>> f.cleaned_data['nullbool2']
+
 # MultipleChoiceField #########################################################
 
 >>> f = MultipleChoiceField(choices=[('1', 'One'), ('2', 'Two')])