mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-03 12:00:12 +03:00
Fixed issue #5926: Ensure that html forms (multipart form data) respect optional fields
This commit is contained in:
parent
0178d3063d
commit
950e0567cd
|
@ -1614,7 +1614,8 @@ class ListField(Field):
|
|||
if len(val) > 0:
|
||||
# Support QueryDict lists in HTML input.
|
||||
return val
|
||||
return html.parse_html_list(dictionary, prefix=self.field_name)
|
||||
return html.parse_html_list(dictionary, prefix=self.field_name, default=empty)
|
||||
|
||||
return dictionary.get(self.field_name, empty)
|
||||
|
||||
def to_internal_value(self, data):
|
||||
|
|
|
@ -607,7 +607,7 @@ class ListSerializer(BaseSerializer):
|
|||
# We override the default field access in order to support
|
||||
# lists in HTML forms.
|
||||
if html.is_html_input(dictionary):
|
||||
return html.parse_html_list(dictionary, prefix=self.field_name)
|
||||
return html.parse_html_list(dictionary, prefix=self.field_name, default=empty)
|
||||
return dictionary.get(self.field_name, empty)
|
||||
|
||||
def run_validation(self, data=empty):
|
||||
|
@ -635,7 +635,7 @@ class ListSerializer(BaseSerializer):
|
|||
List of dicts of native values <- List of dicts of primitive datatypes.
|
||||
"""
|
||||
if html.is_html_input(data):
|
||||
data = html.parse_html_list(data)
|
||||
data = html.parse_html_list(data, default=empty)
|
||||
|
||||
if not isinstance(data, list):
|
||||
message = self.error_messages['not_a_list'].format(
|
||||
|
|
|
@ -12,7 +12,7 @@ def is_html_input(dictionary):
|
|||
return hasattr(dictionary, 'getlist')
|
||||
|
||||
|
||||
def parse_html_list(dictionary, prefix=''):
|
||||
def parse_html_list(dictionary, prefix='', default=[]):
|
||||
"""
|
||||
Used to support list values in HTML forms.
|
||||
Supports lists of primitives and/or dictionaries.
|
||||
|
@ -44,6 +44,8 @@ def parse_html_list(dictionary, prefix=''):
|
|||
{'foo': 'abc', 'bar': 'def'},
|
||||
{'foo': 'hij', 'bar': 'klm'}
|
||||
]
|
||||
|
||||
:returns a list of objects, or the value specified in ``default`` if the list is empty
|
||||
"""
|
||||
ret = {}
|
||||
regex = re.compile(r'^%s\[([0-9]+)\](.*)$' % re.escape(prefix))
|
||||
|
@ -59,7 +61,7 @@ def parse_html_list(dictionary, prefix=''):
|
|||
ret[index][key] = value
|
||||
else:
|
||||
ret[index] = MultiValueDict({key: [value]})
|
||||
return [ret[item] for item in sorted(ret)]
|
||||
return [ret[item] for item in sorted(ret)] if len(ret.keys()) > 0 else default
|
||||
|
||||
|
||||
def parse_html_dict(dictionary, prefix=''):
|
||||
|
|
|
@ -202,3 +202,42 @@ class TestNestedSerializerWithList:
|
|||
|
||||
assert serializer.is_valid()
|
||||
assert serializer.validated_data['nested']['example'] == {1, 2}
|
||||
|
||||
|
||||
class TestNotRequiredNestedSerializerWithMany:
|
||||
def setup(self):
|
||||
class NestedSerializer(serializers.Serializer):
|
||||
one = serializers.IntegerField(max_value=10)
|
||||
|
||||
class TestSerializer(serializers.Serializer):
|
||||
nested = NestedSerializer(required=False, many=True)
|
||||
|
||||
self.Serializer = TestSerializer
|
||||
|
||||
def test_json_validate(self):
|
||||
input_data = {}
|
||||
serializer = self.Serializer(data=input_data)
|
||||
|
||||
# request is empty, therefor 'nested' should not be in serializer.data
|
||||
assert serializer.is_valid()
|
||||
assert 'nested' not in serializer.validated_data
|
||||
|
||||
input_data = {'nested': [{'one': '1'}, {'one': 2}]}
|
||||
serializer = self.Serializer(data=input_data)
|
||||
assert serializer.is_valid()
|
||||
assert 'nested' in serializer.validated_data
|
||||
|
||||
def test_multipart_validate(self):
|
||||
# leave querydict empty
|
||||
input_data = QueryDict('')
|
||||
serializer = self.Serializer(data=input_data)
|
||||
|
||||
# the querydict is empty, therefor 'nested' should not be in serializer.data
|
||||
assert serializer.is_valid()
|
||||
assert 'nested' not in serializer.validated_data
|
||||
|
||||
input_data = QueryDict('nested[0]one=1&nested[1]one=2')
|
||||
|
||||
serializer = self.Serializer(data=input_data)
|
||||
assert serializer.is_valid()
|
||||
assert 'nested' in serializer.validated_data
|
||||
|
|
Loading…
Reference in New Issue
Block a user