Skip to content

Commit a180bde

Browse files
authored
Permit mixed casing of string values for BooleanField validation (#8970)
* be more permissive of mixed casing in validating strings for BooleanField values * undo unnecessary change * lint
1 parent 02d9bfc commit a180bde

File tree

2 files changed

+63
-20
lines changed

2 files changed

+63
-20
lines changed

rest_framework/fields.py

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -664,45 +664,56 @@ class BooleanField(Field):
664664
default_empty_html = False
665665
initial = False
666666
TRUE_VALUES = {
667-
't', 'T',
668-
'y', 'Y', 'yes', 'Yes', 'YES',
669-
'true', 'True', 'TRUE',
670-
'on', 'On', 'ON',
671-
'1', 1,
672-
True
667+
't',
668+
'y',
669+
'yes',
670+
'true',
671+
'on',
672+
'1',
673+
1,
674+
True,
673675
}
674676
FALSE_VALUES = {
675-
'f', 'F',
676-
'n', 'N', 'no', 'No', 'NO',
677-
'false', 'False', 'FALSE',
678-
'off', 'Off', 'OFF',
679-
'0', 0, 0.0,
680-
False
677+
'f',
678+
'n',
679+
'no',
680+
'false',
681+
'off',
682+
'0',
683+
0,
684+
0.0,
685+
False,
681686
}
682-
NULL_VALUES = {'null', 'Null', 'NULL', '', None}
687+
NULL_VALUES = {'null', '', None}
683688

684689
def __init__(self, **kwargs):
685690
if kwargs.get('allow_null', False):
686691
self.default_empty_html = None
687692
self.initial = None
688693
super().__init__(**kwargs)
689694

695+
@staticmethod
696+
def _lower_if_str(value):
697+
if isinstance(value, str):
698+
return value.lower()
699+
return value
700+
690701
def to_internal_value(self, data):
691702
with contextlib.suppress(TypeError):
692-
if data in self.TRUE_VALUES:
703+
if self._lower_if_str(data) in self.TRUE_VALUES:
693704
return True
694-
elif data in self.FALSE_VALUES:
705+
elif self._lower_if_str(data) in self.FALSE_VALUES:
695706
return False
696-
elif data in self.NULL_VALUES and self.allow_null:
707+
elif self._lower_if_str(data) in self.NULL_VALUES and self.allow_null:
697708
return None
698-
self.fail('invalid', input=data)
709+
self.fail("invalid", input=data)
699710

700711
def to_representation(self, value):
701-
if value in self.TRUE_VALUES:
712+
if self._lower_if_str(value) in self.TRUE_VALUES:
702713
return True
703-
elif value in self.FALSE_VALUES:
714+
elif self._lower_if_str(value) in self.FALSE_VALUES:
704715
return False
705-
if value in self.NULL_VALUES and self.allow_null:
716+
if self._lower_if_str(value) in self.NULL_VALUES and self.allow_null:
706717
return None
707718
return bool(value)
708719

tests/test_fields.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,8 +695,24 @@ class TestBooleanField(FieldValues):
695695
Valid and invalid values for `BooleanField`.
696696
"""
697697
valid_inputs = {
698+
'True': True,
699+
'TRUE': True,
700+
'tRuE': True,
701+
't': True,
702+
'T': True,
698703
'true': True,
704+
'on': True,
705+
'ON': True,
706+
'oN': True,
707+
'False': False,
708+
'FALSE': False,
709+
'fALse': False,
710+
'f': False,
711+
'F': False,
699712
'false': False,
713+
'off': False,
714+
'OFF': False,
715+
'oFf': False,
700716
'1': True,
701717
'0': False,
702718
1: True,
@@ -709,8 +725,24 @@ class TestBooleanField(FieldValues):
709725
None: ['This field may not be null.']
710726
}
711727
outputs = {
728+
'True': True,
729+
'TRUE': True,
730+
'tRuE': True,
731+
't': True,
732+
'T': True,
712733
'true': True,
734+
'on': True,
735+
'ON': True,
736+
'oN': True,
737+
'False': False,
738+
'FALSE': False,
739+
'fALse': False,
740+
'f': False,
741+
'F': False,
713742
'false': False,
743+
'off': False,
744+
'OFF': False,
745+
'oFf': False,
714746
'1': True,
715747
'0': False,
716748
1: True,

0 commit comments

Comments
 (0)