Skip to content

Commit fdde44d

Browse files
lrnttomchristie
authored andcommitted
Fix parsing multipart data using a nested serializer with list (#3820)
It is possible that a key in a MultiValueDict has multiple values, lists are represented this way. When accessing a key in a MultiValueDict it only returns the last element of that key. This becomes a problem when parsing an html dict with a list inside of it. To fix this problem we have to get and set the value using .getlist() and .setlist().
1 parent bc3485a commit fdde44d

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

rest_framework/utils/html.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,12 @@ def parse_html_dict(dictionary, prefix=''):
8080
"""
8181
ret = MultiValueDict()
8282
regex = re.compile(r'^%s\.(.+)$' % re.escape(prefix))
83-
for field, value in dictionary.items():
83+
for field in dictionary:
8484
match = regex.match(field)
8585
if not match:
8686
continue
8787
key = match.groups()[0]
88-
ret[key] = value
88+
value = dictionary.getlist(field)
89+
ret.setlist(key, value)
90+
8991
return ret

tests/test_serializer_nested.py

+29
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,32 @@ def test_empty_not_allowed_if_allow_empty_is_set_to_false(self):
167167

168168
expected_errors = {'not_allow_empty': {'non_field_errors': [serializers.ListSerializer.default_error_messages['empty']]}}
169169
assert serializer.errors == expected_errors
170+
171+
172+
class TestNestedSerializerWithList:
173+
def setup(self):
174+
class NestedSerializer(serializers.Serializer):
175+
example = serializers.MultipleChoiceField(choices=[1, 2, 3])
176+
177+
class TestSerializer(serializers.Serializer):
178+
nested = NestedSerializer()
179+
180+
self.Serializer = TestSerializer
181+
182+
def test_nested_serializer_with_list_json(self):
183+
input_data = {
184+
'nested': {
185+
'example': [1, 2],
186+
}
187+
}
188+
serializer = self.Serializer(data=input_data)
189+
190+
assert serializer.is_valid()
191+
assert serializer.validated_data['nested']['example'] == set([1, 2])
192+
193+
def test_nested_serializer_with_list_multipart(self):
194+
input_data = QueryDict('nested.example=1&nested.example=2')
195+
serializer = self.Serializer(data=input_data)
196+
197+
assert serializer.is_valid()
198+
assert serializer.validated_data['nested']['example'] == set([1, 2])

0 commit comments

Comments
 (0)