From b0c5f9db2f28324d77a841f504a24a5b51935552 Mon Sep 17 00:00:00 2001 From: Juan Gutierrez Date: Fri, 3 Jul 2015 12:28:48 -0400 Subject: [PATCH] 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()