diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 4eae004dc6..cb1b28167a 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1639,6 +1639,8 @@ def run_child_validation(self, data): result.append(self.child.run_validation(item)) except ValidationError as e: errors[idx] = e.detail + except DjangoValidationError as e: + errors[idx] = get_error_detail(e) if not errors: return result diff --git a/tests/test_fields.py b/tests/test_fields.py index 648c2a9c9a..51a661ddcb 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -17,6 +17,7 @@ from rest_framework.fields import ( BuiltinSignatureError, DjangoImageField, is_simple_callable ) +from tests.models import UUIDForeignKeyTarget utc = datetime.timezone.utc @@ -2074,6 +2075,35 @@ class TestNestedListField(FieldValues): field = serializers.ListField(child=serializers.ListField(child=serializers.IntegerField())) +class TestListFieldWithDjangoValidationErrors(FieldValues, TestCase): + """ + Values for `ListField` with UUIDField as child + (since UUIDField can throw ValidationErrors from Django). + The idea is to test that Django's ValidationErrors raised + from Django internals are caught and serializers in a way + that is structurally consistent with DRF's ValidationErrors. + """ + + valid_inputs = [] + invalid_inputs = [ + ( + ['not-a-valid-uuid', 'd7364368-d1b3-4455-aaa3-56439b460ca2', 'some-other-invalid-uuid'], + { + 0: [exceptions.ErrorDetail(string='“not-a-valid-uuid” is not a valid UUID.', code='invalid')], + 1: [ + exceptions.ErrorDetail( + string='Invalid pk "d7364368-d1b3-4455-aaa3-56439b460ca2" - object does not exist.', + code='does_not_exist', + ) + ], + 2: [exceptions.ErrorDetail(string='“some-other-invalid-uuid” is not a valid UUID.', code='invalid')], + }, + ), + ] + outputs = {} + field = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=UUIDForeignKeyTarget.objects.all())) + + class TestEmptyListField(FieldValues): """ Values for `ListField` with allow_empty=False flag.