Skip to content

Commit c42df55

Browse files
committed
fix and more tests
1 parent bd57a0a commit c42df55

File tree

2 files changed

+98
-7
lines changed

2 files changed

+98
-7
lines changed

rest_framework/fields.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -227,17 +227,39 @@ def __init__(self, value, display_text, disabled=False):
227227
yield Option(value='n/a', display_text=cutoff_text, disabled=True)
228228

229229

230+
def _get_error_detail_dict(error_dict, default_code):
231+
return {
232+
k: [
233+
ErrorDetail(error.message % (error.params or ()),
234+
code=error.code if error.code else default_code)
235+
for error in errors
236+
] for k, errors in error_dict.items()
237+
}
238+
239+
230240
def get_error_detail(exc_info):
231241
"""
232242
Given a Django ValidationError, return a list of ErrorDetail,
233243
with the `code` populated.
234244
"""
235245
code = getattr(exc_info, 'code', None) or 'invalid'
236-
return [
237-
ErrorDetail(error.message % (error.params or ()),
238-
code=error.code if error.code else code)
239-
for error in exc_info.error_list
240-
]
246+
247+
try:
248+
error_dict = exc_info.error_dict
249+
except AttributeError:
250+
errors = []
251+
for error in exc_info.error_list:
252+
try:
253+
error_dict = error.error_dict
254+
except AttributeError:
255+
detail = ErrorDetail(error.message % (error.params or ()),
256+
code=error.code if error.code else code)
257+
else:
258+
detail = _get_error_detail_dict(error, code)
259+
errors.append(detail)
260+
return errors
261+
else:
262+
return _get_error_detail_dict(error_dict, code)
241263

242264

243265
class CreateOnlyDefault(object):

tests/test_fields.py

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from django.utils.timezone import activate, deactivate, override, utc
1414

1515
import rest_framework
16-
from rest_framework import compat, serializers
16+
from rest_framework import compat, exceptions, serializers
1717
from rest_framework.fields import DjangoImageField, is_simple_callable
1818

1919
try:
@@ -2188,7 +2188,7 @@ class ExampleSerializer(serializers.Serializer):
21882188

21892189
class TestValidationErrorCode:
21902190
@pytest.mark.parametrize('use_list', (False, True))
2191-
def test_validationerror_code(self, use_list):
2191+
def test_validationerror_code_with_msg(self, use_list):
21922192

21932193
class ExampleSerializer(serializers.Serializer):
21942194
password = serializers.CharField()
@@ -2203,3 +2203,72 @@ def validate_password(self, obj):
22032203
serializer.is_valid()
22042204
assert serializer.errors == {'password': ['exc_msg']}
22052205
assert serializer.errors['password'][0].code == 'exc_code'
2206+
2207+
@pytest.mark.parametrize('code', (None, 'exc_code',))
2208+
@pytest.mark.parametrize('use_list', (False, True))
2209+
def test_validationerror_code_with_dict(self, use_list, code):
2210+
2211+
class ExampleSerializer(serializers.Serializer):
2212+
2213+
def validate(self, obj):
2214+
if code is None:
2215+
err = DjangoValidationError({
2216+
'email': 'email error',
2217+
})
2218+
else:
2219+
err = DjangoValidationError({
2220+
'email': DjangoValidationError(
2221+
'email error',
2222+
code=code),
2223+
})
2224+
if use_list:
2225+
err = DjangoValidationError([err])
2226+
raise err
2227+
2228+
serializer = ExampleSerializer(data={})
2229+
serializer.is_valid()
2230+
expected_code = code if code else 'invalid'
2231+
if use_list:
2232+
assert serializer.errors == {
2233+
'non_field_errors': [
2234+
exceptions.ErrorDetail(
2235+
string='email error',
2236+
code=expected_code
2237+
)
2238+
]
2239+
}
2240+
else:
2241+
assert serializer.errors == {
2242+
'email': ['email error'],
2243+
}
2244+
assert serializer.errors['email'][0].code == expected_code
2245+
2246+
@pytest.mark.parametrize('code', (None, 'exc_code',))
2247+
def test_validationerror_code_with_dict_list_same_code(self, code):
2248+
2249+
class ExampleSerializer(serializers.Serializer):
2250+
2251+
def validate(self, obj):
2252+
if code is None:
2253+
raise DjangoValidationError({'email': ['email error 1',
2254+
'email error 2']})
2255+
raise DjangoValidationError({'email': [
2256+
DjangoValidationError('email error 1', code=code),
2257+
DjangoValidationError('email error 2', code=code),
2258+
]})
2259+
2260+
serializer = ExampleSerializer(data={})
2261+
serializer.is_valid()
2262+
expected_code = code if code else 'invalid'
2263+
assert serializer.errors == {
2264+
'email': [
2265+
exceptions.ErrorDetail(
2266+
string='email error 1',
2267+
code=expected_code
2268+
),
2269+
exceptions.ErrorDetail(
2270+
string='email error 2',
2271+
code=expected_code
2272+
),
2273+
]
2274+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy