Skip to content

Commit 1fbe16a

Browse files
authored
Fix BooleanField's allow_null behavior (#8614)
* Fix BooleanField's allow_null behavior * Update rest_framework.fields - Use .get with default value for 'allow_null' kwarg in BooleanField's init
1 parent ee15731 commit 1fbe16a

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

rest_framework/fields.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,12 @@ class BooleanField(Field):
690690
}
691691
NULL_VALUES = {'null', 'Null', 'NULL', '', None}
692692

693+
def __init__(self, **kwargs):
694+
if kwargs.get('allow_null', False):
695+
self.default_empty_html = None
696+
self.initial = None
697+
super().__init__(**kwargs)
698+
693699
def to_internal_value(self, data):
694700
with contextlib.suppress(TypeError):
695701
if data in self.TRUE_VALUES:

tests/test_fields.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ class TestBooleanHTMLInput:
371371
def test_empty_html_checkbox(self):
372372
"""
373373
HTML checkboxes do not send any value, but should be treated
374-
as `False` by BooleanField.
374+
as `False` by BooleanField if allow_null=False.
375375
"""
376376
class TestSerializer(serializers.Serializer):
377377
archived = serializers.BooleanField()
@@ -383,7 +383,8 @@ class TestSerializer(serializers.Serializer):
383383
def test_empty_html_checkbox_not_required(self):
384384
"""
385385
HTML checkboxes do not send any value, but should be treated
386-
as `False` by BooleanField, even if the field is required=False.
386+
as `False` by BooleanField when the field is required=False
387+
and allow_null=False.
387388
"""
388389
class TestSerializer(serializers.Serializer):
389390
archived = serializers.BooleanField(required=False)
@@ -392,6 +393,34 @@ class TestSerializer(serializers.Serializer):
392393
assert serializer.is_valid()
393394
assert serializer.validated_data == {'archived': False}
394395

396+
def test_empty_html_checkbox_allow_null(self):
397+
"""
398+
HTML checkboxes do not send any value and should be treated
399+
as `None` by BooleanField if allow_null is True.
400+
"""
401+
class TestSerializer(serializers.Serializer):
402+
archived = serializers.BooleanField(allow_null=True)
403+
404+
serializer = TestSerializer(data=QueryDict(''))
405+
assert serializer.is_valid()
406+
assert serializer.validated_data == {'archived': None}
407+
408+
def test_empty_html_checkbox_allow_null_with_default(self):
409+
"""
410+
BooleanField should respect default if set and still allow
411+
setting null values.
412+
"""
413+
class TestSerializer(serializers.Serializer):
414+
archived = serializers.BooleanField(allow_null=True, default=True)
415+
416+
serializer = TestSerializer(data=QueryDict(''))
417+
assert serializer.is_valid()
418+
assert serializer.validated_data == {'archived': True}
419+
420+
serializer = TestSerializer(data=QueryDict('archived='))
421+
assert serializer.is_valid()
422+
assert serializer.validated_data == {'archived': None}
423+
395424

396425
class TestHTMLInput:
397426
def test_empty_html_charfield_with_default(self):

0 commit comments

Comments
 (0)