diff --git a/rest_framework/utils/serializer_helpers.py b/rest_framework/utils/serializer_helpers.py index e6bd84f30e..94ac794424 100644 --- a/rest_framework/utils/serializer_helpers.py +++ b/rest_framework/utils/serializer_helpers.py @@ -130,7 +130,14 @@ def __iter__(self): def __getitem__(self, key): field = self.fields[key] value = self.value.get(key) if self.value else None - error = self.errors.get(key) if isinstance(self.errors, dict) else None + + if isinstance(self.errors, dict): + error = self.errors.get(key) + elif isinstance(self.errors, list): + error = {} # normalize list to empty dict for nested children + else: + error = None + if hasattr(field, 'fields'): return NestedBoundField(field, value, error, prefix=self.name + '.') elif getattr(field, '_is_jsonfield', False): diff --git a/tests/test_bound_fields.py b/tests/test_bound_fields.py index eee7d9b852..7e76113d1d 100644 --- a/tests/test_bound_fields.py +++ b/tests/test_bound_fields.py @@ -1,6 +1,7 @@ from django.http import QueryDict from rest_framework import serializers +from rest_framework.exceptions import ValidationError class TestSimpleBoundField: @@ -211,6 +212,29 @@ class ExampleSerializer(serializers.Serializer): rendered_packed = ''.join(rendered.split()) assert rendered_packed == expected_packed + def test_child_bound_field_after_parent_validation_error(self): + class ChildSerializer(serializers.Serializer): + value = serializers.CharField() + + class ParentSerializer(serializers.Serializer): + nested = ChildSerializer() + + def validate_nested(self, nested): + # Raise parent-level (non-field) validation error + raise ValidationError(["parent-level nested error"]) + + serializer = ParentSerializer(data={"nested": {"value": "ignored"}}) + assert not serializer.is_valid() + + # Parent-level error is a list (current problematic case) + assert serializer.errors["nested"] == ["parent-level nested error"] + parent_bound = serializer["nested"] + child_bound = parent_bound["value"] + assert isinstance(child_bound.errors, dict) + assert child_bound.errors == {} + assert child_bound.value == "ignored" + assert child_bound.name == "nested.value" + class TestJSONBoundField: def test_as_form_fields(self):