From dcdd765647b28135dc764f038e9380cf1ccc0ecc Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Thu, 3 Sep 2015 17:27:33 +0200 Subject: [PATCH 1/3] Avoid passing allow_empty to the ListSerializer children. --- rest_framework/serializers.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index c7d4405c59..77120a1089 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -113,8 +113,12 @@ def many_init(cls, *args, **kwargs): kwargs['child'] = cls() return CustomListSerializer(*args, **kwargs) """ + allow_empty = kwargs.pop('allow_empty', True) child_serializer = cls(*args, **kwargs) - list_kwargs = {'child': child_serializer} + list_kwargs = { + 'child': child_serializer, + 'allow_empty': allow_empty, + } list_kwargs.update(dict([ (key, value) for key, value in kwargs.items() if key in LIST_SERIALIZER_KWARGS From 4404d40f6068c5e403ddb7a8716e6b53cc3c6ba9 Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Sun, 6 Sep 2015 23:02:44 +0200 Subject: [PATCH 2/3] Only pass allow_empty to the `ListSerializer` if it was in the arguments. Helps with backward compatibility. --- rest_framework/serializers.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 77120a1089..037939e318 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -113,12 +113,13 @@ def many_init(cls, *args, **kwargs): kwargs['child'] = cls() return CustomListSerializer(*args, **kwargs) """ - allow_empty = kwargs.pop('allow_empty', True) + allow_empty = kwargs.pop('allow_empty', None) child_serializer = cls(*args, **kwargs) list_kwargs = { 'child': child_serializer, - 'allow_empty': allow_empty, } + if allow_empty is not None: + list_kwargs['allow_empty'] = allow_empty list_kwargs.update(dict([ (key, value) for key, value in kwargs.items() if key in LIST_SERIALIZER_KWARGS From aa4818268641d572cc914cbc495f680275643d8e Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Mon, 7 Sep 2015 23:11:01 +0200 Subject: [PATCH 3/3] Add test coverage on allow_empty for nested serializers. --- tests/test_serializer_nested.py | 50 ++++++++++++++++++++++++++++++--- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/tests/test_serializer_nested.py b/tests/test_serializer_nested.py index 22d4deca15..aeb092ee05 100644 --- a/tests/test_serializer_nested.py +++ b/tests/test_serializer_nested.py @@ -79,17 +79,23 @@ class NestedSerializer(serializers.Serializer): class TestSerializer(serializers.Serializer): allow_null = NestedSerializer(many=True, allow_null=True) not_allow_null = NestedSerializer(many=True) + allow_empty = NestedSerializer(many=True, allow_empty=True) + not_allow_empty = NestedSerializer(many=True, allow_empty=False) self.Serializer = TestSerializer def test_null_allowed_if_allow_null_is_set(self): input_data = { 'allow_null': None, - 'not_allow_null': [{'example': '2'}, {'example': '3'}] + 'not_allow_null': [{'example': '2'}, {'example': '3'}], + 'allow_empty': [{'example': '2'}], + 'not_allow_empty': [{'example': '2'}], } expected_data = { 'allow_null': None, - 'not_allow_null': [{'example': 2}, {'example': 3}] + 'not_allow_null': [{'example': 2}, {'example': 3}], + 'allow_empty': [{'example': 2}], + 'not_allow_empty': [{'example': 2}], } serializer = self.Serializer(data=input_data) @@ -99,7 +105,9 @@ def test_null_allowed_if_allow_null_is_set(self): def test_null_is_not_allowed_if_allow_null_is_not_set(self): input_data = { 'allow_null': None, - 'not_allow_null': None + 'not_allow_null': None, + 'allow_empty': [{'example': '2'}], + 'not_allow_empty': [{'example': '2'}], } serializer = self.Serializer(data=input_data) @@ -118,10 +126,44 @@ def validate_allow_null(self, value): input_data = { 'allow_null': None, - 'not_allow_null': [{'example': 2}] + 'not_allow_null': [{'example': 2}], + 'allow_empty': [{'example': 2}], + 'not_allow_empty': [{'example': 2}], } serializer = TestSerializer(data=input_data) assert serializer.is_valid() assert serializer.validated_data == input_data assert TestSerializer.validation_was_run + + def test_empty_allowed_if_allow_empty_is_set(self): + input_data = { + 'allow_null': [{'example': '2'}], + 'not_allow_null': [{'example': '2'}], + 'allow_empty': [], + 'not_allow_empty': [{'example': '2'}], + } + expected_data = { + 'allow_null': [{'example': 2}], + 'not_allow_null': [{'example': 2}], + 'allow_empty': [], + 'not_allow_empty': [{'example': 2}], + } + serializer = self.Serializer(data=input_data) + + assert serializer.is_valid(), serializer.errors + assert serializer.validated_data == expected_data + + def test_empty_not_allowed_if_allow_empty_is_set_to_false(self): + input_data = { + 'allow_null': [{'example': '2'}], + 'not_allow_null': [{'example': '2'}], + 'allow_empty': [], + 'not_allow_empty': [], + } + serializer = self.Serializer(data=input_data) + + assert not serializer.is_valid() + + expected_errors = {'not_allow_empty': {'non_field_errors': [serializers.ListSerializer.default_error_messages['empty']]}} + assert serializer.errors == expected_errors