Skip to content

Commit 22ffeaf

Browse files
committed
Merge pull request #2311 from tomchristie/allow-empty-text-or-boolean-html-input-if-not-required
Fixes for behavior with empty HTML fields.
2 parents e8b4641 + 1087ccb commit 22ffeaf

File tree

2 files changed

+44
-19
lines changed

2 files changed

+44
-19
lines changed

rest_framework/fields.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,11 @@ def __init__(self, read_only=False, write_only=False,
184184
self.style = {} if style is None else style
185185
self.allow_null = allow_null
186186

187-
if allow_null and self.default_empty_html is empty:
188-
# HTML input cannot represent `None` values, so we need to
189-
# forcibly coerce empty HTML values to `None` if `allow_null=True`.
190-
self.default_empty_html = None
191-
192-
if default is not empty:
193-
self.default_empty_html = default
187+
if self.default_empty_html is not empty:
188+
if not required:
189+
self.default_empty_html = empty
190+
elif default is not empty:
191+
self.default_empty_html = default
194192

195193
if validators is not None:
196194
self.validators = validators[:]
@@ -562,6 +560,11 @@ def __init__(self, **kwargs):
562560
message = self.error_messages['min_length'].format(min_length=min_length)
563561
self.validators.append(MinLengthValidator(min_length, message=message))
564562

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+
565568
def run_validation(self, data=empty):
566569
# Test for the empty string here so that it does not get validated,
567570
# and so that subclasses do not need to handle it explicitly

tests/test_fields.py

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -215,25 +215,47 @@ class MockHTMLDict(dict):
215215
assert serializer.validated_data == {'archived': False}
216216

217217

218+
class MockHTMLDict(dict):
219+
"""
220+
This class mocks up a dictionary like object, that behaves
221+
as if it was returned for multipart or urlencoded data.
222+
"""
223+
getlist = None
224+
225+
218226
class TestCharHTMLInput:
219-
def setup(self):
227+
def test_empty_html_checkbox(self):
220228
class TestSerializer(serializers.Serializer):
221229
message = serializers.CharField(default='happy')
222-
self.Serializer = TestSerializer
223230

224-
def test_empty_html_checkbox(self):
225-
"""
226-
HTML checkboxes do not send any value, but should be treated
227-
as `False` by BooleanField.
228-
"""
229-
# This class mocks up a dictionary like object, that behaves
230-
# as if it was returned for multipart or urlencoded data.
231-
class MockHTMLDict(dict):
232-
getlist = None
233-
serializer = self.Serializer(data=MockHTMLDict())
231+
serializer = TestSerializer(data=MockHTMLDict())
234232
assert serializer.is_valid()
235233
assert serializer.validated_data == {'message': 'happy'}
236234

235+
def test_empty_html_checkbox_allow_null(self):
236+
class TestSerializer(serializers.Serializer):
237+
message = serializers.CharField(allow_null=True)
238+
239+
serializer = TestSerializer(data=MockHTMLDict())
240+
assert serializer.is_valid()
241+
assert serializer.validated_data == {'message': None}
242+
243+
def test_empty_html_checkbox_allow_null_allow_blank(self):
244+
class TestSerializer(serializers.Serializer):
245+
message = serializers.CharField(allow_null=True, allow_blank=True)
246+
247+
serializer = TestSerializer(data=MockHTMLDict({}))
248+
assert serializer.is_valid()
249+
assert serializer.validated_data == {'message': ''}
250+
251+
def test_empty_html_required_false(self):
252+
class TestSerializer(serializers.Serializer):
253+
message = serializers.CharField(required=False)
254+
255+
serializer = TestSerializer(data=MockHTMLDict())
256+
assert serializer.is_valid()
257+
assert serializer.validated_data == {}
258+
237259

238260
class TestCreateOnlyDefault:
239261
def setup(self):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy