Skip to content

Commit

Permalink
Merge pull request #2330 from tomchristie/better-blank-html-behavior
Browse files Browse the repository at this point in the history
Better behavior with null and '' for blank HTML fields.
  • Loading branch information
tomchristie committed Dec 20, 2014
2 parents d109ae0 + 77e3021 commit ffb8d56
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 15 deletions.
13 changes: 5 additions & 8 deletions rest_framework/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,11 @@ def get_value(self, dictionary):
return empty
return self.default_empty_html
ret = dictionary[self.field_name]
return self.default_empty_html if (ret == '') else ret
if ret == '' and self.allow_null:
# If the field is blank, and null is a valid value then
# determine if we should use null instead.
return '' if getattr(self, 'allow_blank', False) else None
return ret
return dictionary.get(self.field_name, empty)

def get_attribute(self, instance):
Expand Down Expand Up @@ -545,8 +549,6 @@ class CharField(Field):
'min_length': _('Ensure this field has at least {min_length} characters.')
}
initial = ''
coerce_blank_to_null = False
default_empty_html = ''

def __init__(self, **kwargs):
self.allow_blank = kwargs.pop('allow_blank', False)
Expand All @@ -560,11 +562,6 @@ def __init__(self, **kwargs):
message = self.error_messages['min_length'].format(min_length=min_length)
self.validators.append(MinLengthValidator(min_length, message=message))

if self.allow_null and (not self.allow_blank) and (self.default is empty):
# HTML input cannot represent `None` values, so we need to
# forcibly coerce empty HTML values to `None` if `allow_null=True`.
self.default_empty_html = None

def run_validation(self, data=empty):
# Test for the empty string here so that it does not get validated,
# and so that subclasses do not need to handle it explicitly
Expand Down
22 changes: 15 additions & 7 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,32 +223,40 @@ class MockHTMLDict(dict):
getlist = None


class TestCharHTMLInput:
def test_empty_html_checkbox(self):
class TestHTMLInput:
def test_empty_html_charfield(self):
class TestSerializer(serializers.Serializer):
message = serializers.CharField(default='happy')

serializer = TestSerializer(data=MockHTMLDict())
assert serializer.is_valid()
assert serializer.validated_data == {'message': 'happy'}

def test_empty_html_checkbox_allow_null(self):
def test_empty_html_charfield_allow_null(self):
class TestSerializer(serializers.Serializer):
message = serializers.CharField(allow_null=True)

serializer = TestSerializer(data=MockHTMLDict())
serializer = TestSerializer(data=MockHTMLDict({'message': ''}))
assert serializer.is_valid()
assert serializer.validated_data == {'message': None}

def test_empty_html_checkbox_allow_null_allow_blank(self):
def test_empty_html_datefield_allow_null(self):
class TestSerializer(serializers.Serializer):
expiry = serializers.DateField(allow_null=True)

serializer = TestSerializer(data=MockHTMLDict({'expiry': ''}))
assert serializer.is_valid()
assert serializer.validated_data == {'expiry': None}

def test_empty_html_charfield_allow_null_allow_blank(self):
class TestSerializer(serializers.Serializer):
message = serializers.CharField(allow_null=True, allow_blank=True)

serializer = TestSerializer(data=MockHTMLDict({}))
serializer = TestSerializer(data=MockHTMLDict({'message': ''}))
assert serializer.is_valid()
assert serializer.validated_data == {'message': ''}

def test_empty_html_required_false(self):
def test_empty_html_charfield_required_false(self):
class TestSerializer(serializers.Serializer):
message = serializers.CharField(required=False)

Expand Down

0 comments on commit ffb8d56

Please sign in to comment.