From b0c5f9db2f28324d77a841f504a24a5b51935552 Mon Sep 17 00:00:00 2001 From: Juan Gutierrez Date: Fri, 3 Jul 2015 12:28:48 -0400 Subject: [PATCH 1/3] allow a non-required nested serializer to validate correctly when receiving multipart data --- rest_framework/serializers.py | 2 +- tests/test_serializer_nested.py | 43 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 7afddfd82..80b7c6d6d 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -367,7 +367,7 @@ class Serializer(BaseSerializer): # We override the default field access in order to support # nested HTML forms. if html.is_html_input(dictionary): - return html.parse_html_dict(dictionary, prefix=self.field_name) + return html.parse_html_dict(dictionary, prefix=self.field_name) or empty return dictionary.get(self.field_name, empty) def run_validation(self, data=empty): diff --git a/tests/test_serializer_nested.py b/tests/test_serializer_nested.py index f5e4b26ad..24415db60 100644 --- a/tests/test_serializer_nested.py +++ b/tests/test_serializer_nested.py @@ -38,3 +38,46 @@ class TestNestedSerializer: } serializer = self.Serializer() assert serializer.data == expected_data + + +class TestNotRequiredNestedSerializer: + def setup(self): + class NestedSerializer(serializers.Serializer): + one = serializers.IntegerField(max_value=10) + + class TestSerializer(serializers.Serializer): + nested = NestedSerializer(required=False) + + self.Serializer = TestSerializer + + class FakeMultiDict(dict): + """ + Use this to fake a `format="multipart"` request, because + `utils.is_html_input()` returns `True` when the dict object has + an attribute of "getlist". + """ + def getlist(self, value, default=None): + if value in self: + return [self[value]] + else: + return [] if default is None else default + + self.FakeMultiDict = FakeMultiDict + + def test_json_validate(self): + input_data = {} + serializer = self.Serializer(data=input_data) + assert serializer.is_valid() + + input_data = {'nested': {'one': '1'}} + serializer = self.Serializer(data=input_data) + assert serializer.is_valid() + + def test_multipart_validate(self): + input_data = self.FakeMultiDict() + serializer = self.Serializer(data=input_data) + assert serializer.is_valid() + + input_data = self.FakeMultiDict(**{'nested.one': '1'}) + serializer = self.Serializer(data=input_data) + assert serializer.is_valid() From 35db2b142ff49c0ea648921244d16976e0d5d41e Mon Sep 17 00:00:00 2001 From: Juan Gutierrez Date: Wed, 8 Jul 2015 08:19:42 -0400 Subject: [PATCH 2/3] remove FakeMultiDict definition in nested serializer tests and replace with django QueryDict --- tests/test_serializer_nested.py | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/tests/test_serializer_nested.py b/tests/test_serializer_nested.py index 24415db60..99f60c2a6 100644 --- a/tests/test_serializer_nested.py +++ b/tests/test_serializer_nested.py @@ -1,3 +1,5 @@ +from django.http import QueryDict + from rest_framework import serializers @@ -50,20 +52,6 @@ class TestNotRequiredNestedSerializer: self.Serializer = TestSerializer - class FakeMultiDict(dict): - """ - Use this to fake a `format="multipart"` request, because - `utils.is_html_input()` returns `True` when the dict object has - an attribute of "getlist". - """ - def getlist(self, value, default=None): - if value in self: - return [self[value]] - else: - return [] if default is None else default - - self.FakeMultiDict = FakeMultiDict - def test_json_validate(self): input_data = {} serializer = self.Serializer(data=input_data) @@ -74,10 +62,10 @@ class TestNotRequiredNestedSerializer: assert serializer.is_valid() def test_multipart_validate(self): - input_data = self.FakeMultiDict() + input_data = QueryDict() serializer = self.Serializer(data=input_data) assert serializer.is_valid() - input_data = self.FakeMultiDict(**{'nested.one': '1'}) + input_data = QueryDict('nested[one]=1') serializer = self.Serializer(data=input_data) assert serializer.is_valid() From 2887fc4a0bc587f548d90dd07efa5eb8146b3f8e Mon Sep 17 00:00:00 2001 From: Juan Gutierrez Date: Wed, 8 Jul 2015 08:25:12 -0400 Subject: [PATCH 3/3] update QueryDict initialization to satisfy older versions of Django --- tests/test_serializer_nested.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_serializer_nested.py b/tests/test_serializer_nested.py index 99f60c2a6..b14a58c9e 100644 --- a/tests/test_serializer_nested.py +++ b/tests/test_serializer_nested.py @@ -62,7 +62,7 @@ class TestNotRequiredNestedSerializer: assert serializer.is_valid() def test_multipart_validate(self): - input_data = QueryDict() + input_data = QueryDict('') serializer = self.Serializer(data=input_data) assert serializer.is_valid()