Skip to content

Commit ffb8d56

Browse files
committed
Merge pull request #2330 from tomchristie/better-blank-html-behavior
Better behavior with null and '' for blank HTML fields.
2 parents d109ae0 + 77e3021 commit ffb8d56

File tree

2 files changed

+20
-15
lines changed

2 files changed

+20
-15
lines changed

rest_framework/fields.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,11 @@ def get_value(self, dictionary):
273273
return empty
274274
return self.default_empty_html
275275
ret = dictionary[self.field_name]
276-
return self.default_empty_html if (ret == '') else ret
276+
if ret == '' and self.allow_null:
277+
# If the field is blank, and null is a valid value then
278+
# determine if we should use null instead.
279+
return '' if getattr(self, 'allow_blank', False) else None
280+
return ret
277281
return dictionary.get(self.field_name, empty)
278282

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

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

563-
if self.allow_null and (not self.allow_blank) and (self.default is empty):
564-
# HTML input cannot represent `None` values, so we need to
565-
# forcibly coerce empty HTML values to `None` if `allow_null=True`.
566-
self.default_empty_html = None
567-
568565
def run_validation(self, data=empty):
569566
# Test for the empty string here so that it does not get validated,
570567
# and so that subclasses do not need to handle it explicitly

tests/test_fields.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -223,32 +223,40 @@ class MockHTMLDict(dict):
223223
getlist = None
224224

225225

226-
class TestCharHTMLInput:
227-
def test_empty_html_checkbox(self):
226+
class TestHTMLInput:
227+
def test_empty_html_charfield(self):
228228
class TestSerializer(serializers.Serializer):
229229
message = serializers.CharField(default='happy')
230230

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

235-
def test_empty_html_checkbox_allow_null(self):
235+
def test_empty_html_charfield_allow_null(self):
236236
class TestSerializer(serializers.Serializer):
237237
message = serializers.CharField(allow_null=True)
238238

239-
serializer = TestSerializer(data=MockHTMLDict())
239+
serializer = TestSerializer(data=MockHTMLDict({'message': ''}))
240240
assert serializer.is_valid()
241241
assert serializer.validated_data == {'message': None}
242242

243-
def test_empty_html_checkbox_allow_null_allow_blank(self):
243+
def test_empty_html_datefield_allow_null(self):
244+
class TestSerializer(serializers.Serializer):
245+
expiry = serializers.DateField(allow_null=True)
246+
247+
serializer = TestSerializer(data=MockHTMLDict({'expiry': ''}))
248+
assert serializer.is_valid()
249+
assert serializer.validated_data == {'expiry': None}
250+
251+
def test_empty_html_charfield_allow_null_allow_blank(self):
244252
class TestSerializer(serializers.Serializer):
245253
message = serializers.CharField(allow_null=True, allow_blank=True)
246254

247-
serializer = TestSerializer(data=MockHTMLDict({}))
255+
serializer = TestSerializer(data=MockHTMLDict({'message': ''}))
248256
assert serializer.is_valid()
249257
assert serializer.validated_data == {'message': ''}
250258

251-
def test_empty_html_required_false(self):
259+
def test_empty_html_charfield_required_false(self):
252260
class TestSerializer(serializers.Serializer):
253261
message = serializers.CharField(required=False)
254262

0 commit comments

Comments
 (0)