mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-25 11:04:02 +03:00
Handle Django's ValidationErrors in ListField (#6423)
Without this, Django's ValidationErrors will bypass the error collection from ListField's children. Here is an example that illustrates this change. Consider a Serializer that uses ListField like this: ```python class SomeSerializer(serializers.Serializer): uuids = serializers.ListField( child=serializers.PrimaryKeyRelatedField( queryset=Model.objects.something(), validators=[SomeCustomValidator()] ) ) ``` Validating data that looks like this works fine: ```python {uuids: ['some-valid-uuid', 'some-valid-uuid']} ``` Raising a DRF ValidationError for one of the children works fine, giving an error object like: ```python {'uuids': {0: ErrorDetail(string='Some validation error')}} ``` Raising a Django ValidationError for one of the children works differently (which serializers.PrimaryKeyRelatedField can do in some cases, like when the uuid is malformed). It gives an error object like: ```python {'uuids': ["'X' is not a valid UUID."]} ``` Handling Django's ValidationErrors in ListField explicitly (like in this pull request), will maintain a regular error interface in this case: ```python {'uuids': {0: ErrorDetail(string="'X' is not a valid UUID.")}} ```
This commit is contained in:
parent
cc3c89a11c
commit
ee15731cbc
|
@ -1639,6 +1639,8 @@ class ListField(Field):
|
||||||
result.append(self.child.run_validation(item))
|
result.append(self.child.run_validation(item))
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
errors[idx] = e.detail
|
errors[idx] = e.detail
|
||||||
|
except DjangoValidationError as e:
|
||||||
|
errors[idx] = get_error_detail(e)
|
||||||
|
|
||||||
if not errors:
|
if not errors:
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -17,6 +17,7 @@ from rest_framework import exceptions, serializers
|
||||||
from rest_framework.fields import (
|
from rest_framework.fields import (
|
||||||
BuiltinSignatureError, DjangoImageField, is_simple_callable
|
BuiltinSignatureError, DjangoImageField, is_simple_callable
|
||||||
)
|
)
|
||||||
|
from tests.models import UUIDForeignKeyTarget
|
||||||
|
|
||||||
utc = datetime.timezone.utc
|
utc = datetime.timezone.utc
|
||||||
|
|
||||||
|
@ -2074,6 +2075,35 @@ class TestNestedListField(FieldValues):
|
||||||
field = serializers.ListField(child=serializers.ListField(child=serializers.IntegerField()))
|
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):
|
class TestEmptyListField(FieldValues):
|
||||||
"""
|
"""
|
||||||
Values for `ListField` with allow_empty=False flag.
|
Values for `ListField` with allow_empty=False flag.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user