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
This commit is contained in:
Russell Keith-Magee 2009-05-02 14:52:34 +00:00
parent 95bcb70b56
commit f6cca736a0
2 changed files with 31 additions and 8 deletions

View File

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

View File

@ -1077,6 +1077,10 @@ False
True True
>>> f.clean(0) >>> f.clean(0)
False False
>>> f.clean('1')
True
>>> f.clean('0')
False
>>> f.clean('Django rocks') >>> f.clean('Django rocks')
True True
@ -1201,7 +1205,10 @@ True
>>> f.clean(False) >>> f.clean(False)
False False
>>> f.clean(None) >>> f.clean(None)
>>> f.clean('0')
False
>>> f.clean('1') >>> f.clean('1')
True
>>> f.clean('2') >>> f.clean('2')
>>> f.clean('3') >>> f.clean('3')
>>> f.clean('hello') >>> f.clean('hello')
@ -1220,6 +1227,21 @@ True
>>> f.cleaned_data['hidden_nullbool2'] >>> f.cleaned_data['hidden_nullbool2']
False 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 ######################################################### # MultipleChoiceField #########################################################
>>> f = MultipleChoiceField(choices=[('1', 'One'), ('2', 'Two')]) >>> f = MultipleChoiceField(choices=[('1', 'One'), ('2', 'Two')])