Skip to content

Commit

Permalink
Fix parsing multipart data using a nested serializer with list (#3820)
Browse files Browse the repository at this point in the history
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().
  • Loading branch information
lrnt authored and tomchristie committed Jun 23, 2016
1 parent bc3485a commit fdde44d
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
6 changes: 4 additions & 2 deletions rest_framework/utils/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,12 @@ def parse_html_dict(dictionary, prefix=''):
"""
ret = MultiValueDict()
regex = re.compile(r'^%s\.(.+)$' % re.escape(prefix))
for field, value in dictionary.items():
for field in dictionary:
match = regex.match(field)
if not match:
continue
key = match.groups()[0]
ret[key] = value
value = dictionary.getlist(field)
ret.setlist(key, value)

return ret
29 changes: 29 additions & 0 deletions tests/test_serializer_nested.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,32 @@ def test_empty_not_allowed_if_allow_empty_is_set_to_false(self):

expected_errors = {'not_allow_empty': {'non_field_errors': [serializers.ListSerializer.default_error_messages['empty']]}}
assert serializer.errors == expected_errors


class TestNestedSerializerWithList:
def setup(self):
class NestedSerializer(serializers.Serializer):
example = serializers.MultipleChoiceField(choices=[1, 2, 3])

class TestSerializer(serializers.Serializer):
nested = NestedSerializer()

self.Serializer = TestSerializer

def test_nested_serializer_with_list_json(self):
input_data = {
'nested': {
'example': [1, 2],
}
}
serializer = self.Serializer(data=input_data)

assert serializer.is_valid()
assert serializer.validated_data['nested']['example'] == set([1, 2])

def test_nested_serializer_with_list_multipart(self):
input_data = QueryDict('nested.example=1&nested.example=2')
serializer = self.Serializer(data=input_data)

assert serializer.is_valid()
assert serializer.validated_data['nested']['example'] == set([1, 2])

0 comments on commit fdde44d

Please sign in to comment.