From ec7f7d02f3423df9ea3a4f3dd7cd9f6d85a6c5be Mon Sep 17 00:00:00 2001 From: Reupen Shah Date: Sun, 17 Mar 2019 17:14:42 +0000 Subject: [PATCH] Enforce allow_empty=False during partial validation of parent serializer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs #6509 This enforces allow_empty=True when a ListSerializer is a child of another serializer and partial validation is being performed on the parent serializer. This is because partial validation should allow fields to be omitted, but should not cause values that are invalid without partial validation to become valid. This effectively reverts #4222. None of the tests added in that PR fail if the associated change is removed, so I‘m not sure what that PR was trying to fix. --- rest_framework/serializers.py | 7 ------ tests/test_serializer_lists.py | 45 ++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 742fa65771..d1950d9685 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -592,10 +592,6 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.child.bind(field_name='', parent=self) - def bind(self, field_name, parent): - super().bind(field_name, parent) - self.partial = self.parent.partial - def get_initial(self): if hasattr(self, 'initial_data'): return self.to_representation(self.initial_data) @@ -647,9 +643,6 @@ def to_internal_value(self, data): }, code='not_a_list') if not self.allow_empty and len(data) == 0: - if self.parent and self.partial: - raise SkipField() - message = self.error_messages['empty'] raise ValidationError({ api_settings.NON_FIELD_ERRORS_KEY: [message] diff --git a/tests/test_serializer_lists.py b/tests/test_serializer_lists.py index 12ed78b84a..98e72385a2 100644 --- a/tests/test_serializer_lists.py +++ b/tests/test_serializer_lists.py @@ -1,7 +1,9 @@ +import pytest from django.http import QueryDict from django.utils.datastructures import MultiValueDict from rest_framework import serializers +from rest_framework.exceptions import ErrorDetail class BasicObject: @@ -223,6 +225,49 @@ def test_validate_html_input(self): assert serializer.validated_data == expected_output +class TestNestedListSerializerAllowEmpty: + """Tests the behaviour of allow_empty=False when a ListSerializer is used as a field.""" + + @pytest.mark.parametrize('partial', (False, True)) + def test_allow_empty_true(self, partial): + """ + If allow_empty is True, empty lists should be allowed regardless of the value + of partial on the parent serializer. + """ + class ChildSerializer(serializers.Serializer): + id = serializers.IntegerField() + + class ParentSerializer(serializers.Serializer): + ids = ChildSerializer(many=True, allow_empty=True) + + serializer = ParentSerializer(data={'ids': []}, partial=partial) + assert serializer.is_valid() + assert serializer.validated_data == { + 'ids': [], + } + + @pytest.mark.parametrize('partial', (False, True)) + def test_allow_empty_false(self, partial): + """ + If allow_empty is False, empty lists should fail validation regardless of the value + of partial on the parent serializer. + """ + class ChildSerializer(serializers.Serializer): + id = serializers.IntegerField() + + class ParentSerializer(serializers.Serializer): + ids = ChildSerializer(many=True, allow_empty=False) + + serializer = ParentSerializer(data={'ids': []}, partial=partial) + assert not serializer.is_valid() + assert serializer.errors == { + 'ids': { + 'non_field_errors': [ + ErrorDetail(string='This list may not be empty.', code='empty')], + } + } + + class TestNestedListOfListsSerializer: def setup(self): class TestSerializer(serializers.Serializer): pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy