get_error_detail: use error_dict/error_list (#5785)

This commit is contained in:
Daniel Hahler 2018-07-06 10:44:58 +02:00 committed by Carlton Gibson
parent 6511b52cca
commit 3578bd6883
2 changed files with 105 additions and 5 deletions

View File

@ -233,10 +233,21 @@ def get_error_detail(exc_info):
with the `code` populated.
"""
code = getattr(exc_info, 'code', None) or 'invalid'
try:
error_dict = exc_info.error_dict
except AttributeError:
return [
ErrorDetail(msg, code=code)
for msg in exc_info.messages
]
ErrorDetail(error.message % (error.params or ()),
code=error.code if error.code else code)
for error in exc_info.error_list]
return {
k: [
ErrorDetail(error.message % (error.params or ()),
code=error.code if error.code else code)
for error in errors
] for k, errors in error_dict.items()
}
class CreateOnlyDefault(object):

View File

@ -6,13 +6,14 @@ import uuid
from decimal import ROUND_DOWN, ROUND_UP, Decimal
import pytest
from django.core.exceptions import ValidationError as DjangoValidationError
from django.http import QueryDict
from django.test import TestCase, override_settings
from django.utils import six
from django.utils.timezone import activate, deactivate, override, utc
import rest_framework
from rest_framework import compat, serializers
from rest_framework import compat, exceptions, serializers
from rest_framework.fields import DjangoImageField, is_simple_callable
try:
@ -2183,3 +2184,91 @@ class TestSerializerMethodField:
"'ExampleSerializer', because it is the same as the default "
"method name. Remove the `method_name` argument."
)
class TestValidationErrorCode:
@pytest.mark.parametrize('use_list', (False, True))
def test_validationerror_code_with_msg(self, use_list):
class ExampleSerializer(serializers.Serializer):
password = serializers.CharField()
def validate_password(self, obj):
err = DjangoValidationError('exc_msg', code='exc_code')
if use_list:
err = DjangoValidationError([err])
raise err
serializer = ExampleSerializer(data={'password': 123})
serializer.is_valid()
assert serializer.errors == {'password': ['exc_msg']}
assert serializer.errors['password'][0].code == 'exc_code'
@pytest.mark.parametrize('code', (None, 'exc_code',))
@pytest.mark.parametrize('use_list', (False, True))
def test_validationerror_code_with_dict(self, use_list, code):
class ExampleSerializer(serializers.Serializer):
def validate(self, obj):
if code is None:
err = DjangoValidationError({
'email': 'email error',
})
else:
err = DjangoValidationError({
'email': DjangoValidationError(
'email error',
code=code),
})
if use_list:
err = DjangoValidationError([err])
raise err
serializer = ExampleSerializer(data={})
serializer.is_valid()
expected_code = code if code else 'invalid'
if use_list:
assert serializer.errors == {
'non_field_errors': [
exceptions.ErrorDetail(
string='email error',
code=expected_code
)
]
}
else:
assert serializer.errors == {
'email': ['email error'],
}
assert serializer.errors['email'][0].code == expected_code
@pytest.mark.parametrize('code', (None, 'exc_code',))
def test_validationerror_code_with_dict_list_same_code(self, code):
class ExampleSerializer(serializers.Serializer):
def validate(self, obj):
if code is None:
raise DjangoValidationError({'email': ['email error 1',
'email error 2']})
raise DjangoValidationError({'email': [
DjangoValidationError('email error 1', code=code),
DjangoValidationError('email error 2', code=code),
]})
serializer = ExampleSerializer(data={})
serializer.is_valid()
expected_code = code if code else 'invalid'
assert serializer.errors == {
'email': [
exceptions.ErrorDetail(
string='email error 1',
code=expected_code
),
exceptions.ErrorDetail(
string='email error 2',
code=expected_code
),
]
}