Allow nullable BooleanField in Django 2.1 (#6183)

* Add tests for BooleanField when nullable

* Allow nullable BooleanField in Django 2.1

* Drop 'BooleanField.allow_null' check

* Remove conflicting false/null values
This commit is contained in:
Ryan P Kilby 2018-09-13 09:25:03 -07:00 committed by Tom Christie
parent 5f1f2b1003
commit fc6cbb5b26
3 changed files with 37 additions and 6 deletions

View File

@ -674,10 +674,7 @@ class BooleanField(Field):
'0', 0, 0.0,
False
}
def __init__(self, **kwargs):
assert 'allow_null' not in kwargs, '`allow_null` is not a valid option. Use `NullBooleanField` instead.'
super(BooleanField, self).__init__(**kwargs)
NULL_VALUES = {'null', 'Null', 'NULL', '', None}
def to_internal_value(self, data):
try:
@ -685,6 +682,8 @@ class BooleanField(Field):
return True
elif data in self.FALSE_VALUES:
return False
elif data in self.NULL_VALUES and self.allow_null:
return None
except TypeError: # Input is an unhashable type
pass
self.fail('invalid', input=data)
@ -694,6 +693,8 @@ class BooleanField(Field):
return True
elif value in self.FALSE_VALUES:
return False
if value in self.NULL_VALUES and self.allow_null:
return None
return bool(value)
@ -718,7 +719,7 @@ class NullBooleanField(Field):
'0', 0, 0.0,
False
}
NULL_VALUES = {'n', 'N', 'null', 'Null', 'NULL', '', None}
NULL_VALUES = {'null', 'Null', 'NULL', '', None}
def __init__(self, **kwargs):
assert 'allow_null' not in kwargs, '`allow_null` is not a valid option.'

View File

@ -657,7 +657,7 @@ class TestBooleanField(FieldValues):
class TestNullBooleanField(TestBooleanField):
"""
Valid and invalid values for `BooleanField`.
Valid and invalid values for `NullBooleanField`.
"""
valid_inputs = {
'true': True,
@ -682,6 +682,16 @@ class TestNullBooleanField(TestBooleanField):
field = serializers.NullBooleanField()
class TestNullableBooleanField(TestNullBooleanField):
"""
Valid and invalid values for `BooleanField` when `allow_null=True`.
"""
@property
def field(self):
return serializers.BooleanField(allow_null=True)
# String types...
class TestCharField(FieldValues):

View File

@ -12,6 +12,7 @@ import decimal
import sys
from collections import OrderedDict
import django
import pytest
from django.core.exceptions import ImproperlyConfigured
from django.core.validators import (
@ -220,6 +221,25 @@ class TestRegularFieldMappings(TestCase):
)
self.assertEqual(unicode_repr(TestSerializer()), expected)
# merge this into test_regular_fields / RegularFieldsModel when
# Django 2.1 is the minimum supported version
@pytest.mark.skipif(django.VERSION < (2, 1), reason='Django version < 2.1')
def test_nullable_boolean_field(self):
class NullableBooleanModel(models.Model):
field = models.BooleanField(null=True, default=False)
class NullableBooleanSerializer(serializers.ModelSerializer):
class Meta:
model = NullableBooleanModel
fields = ['field']
expected = dedent("""
NullableBooleanSerializer():
field = BooleanField(allow_null=True, required=False)
""")
self.assertEqual(unicode_repr(NullableBooleanSerializer()), expected)
def test_method_field(self):
"""
Properties and methods on the model should be allowed as `Meta.fields`