mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-11-21 17:16:47 +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))
|
||||
except ValidationError as e:
|
||||
errors[idx] = e.detail
|
||||
except DjangoValidationError as e:
|
||||
errors[idx] = get_error_detail(e)
|
||||
|
||||
if not errors:
|
||||
return result
|
||||
|
|
|
@ -17,6 +17,7 @@ from rest_framework import exceptions, serializers
|
|||
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.
|
||||
|
|
Loading…
Reference in New Issue
Block a user