Skip to content

Commit 6bf5db0

Browse files
committed
[fields] Format error message only if params exist
This prevents exceptions when the error message contains `%`, but is not intended for formatting. Django itself does the same: https://github.com/django/django/blob/6866c91b638de5368c18713fa851bfe56253ea55/django/core/exceptions.py#L168-L169 Fixes encode#6622
1 parent 1a0a8dd commit 6bf5db0

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

rest_framework/fields.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,12 @@ def get_error_detail(exc_info):
239239
error_dict = exc_info.error_dict
240240
except AttributeError:
241241
return [
242-
ErrorDetail(error.message % (error.params or ()),
242+
ErrorDetail((error.message % error.params) if error.params else error.message,
243243
code=error.code if error.code else code)
244244
for error in exc_info.error_list]
245245
return {
246246
k: [
247-
ErrorDetail(error.message % (error.params or ()),
247+
ErrorDetail((error.message % error.params) if error.params else error.message,
248248
code=error.code if error.code else code)
249249
for error in errors
250250
] for k, errors in error_dict.items()

tests/test_fields.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2230,14 +2230,33 @@ class ExampleSerializer(serializers.Serializer):
22302230
password = serializers.CharField()
22312231

22322232
def validate_password(self, obj):
2233-
err = DjangoValidationError('exc_msg', code='exc_code')
2233+
err = DjangoValidationError(
2234+
'exc_msg %s', code='exc_code', params=('exc_param',),
2235+
)
22342236
if use_list:
22352237
err = DjangoValidationError([err])
22362238
raise err
22372239

22382240
serializer = ExampleSerializer(data={'password': 123})
22392241
serializer.is_valid()
2240-
assert serializer.errors == {'password': ['exc_msg']}
2242+
assert serializer.errors == {'password': ['exc_msg exc_param']}
2243+
assert serializer.errors['password'][0].code == 'exc_code'
2244+
2245+
@pytest.mark.parametrize('use_list', (False, True))
2246+
def test_validationerror_code_with_msg_including_percent(self, use_list):
2247+
2248+
class ExampleSerializer(serializers.Serializer):
2249+
password = serializers.CharField()
2250+
2251+
def validate_password(self, obj):
2252+
err = DjangoValidationError('exc_msg with %', code='exc_code')
2253+
if use_list:
2254+
err = DjangoValidationError([err])
2255+
raise err
2256+
2257+
serializer = ExampleSerializer(data={'password': 123})
2258+
serializer.is_valid()
2259+
assert serializer.errors == {'password': ['exc_msg with %']}
22412260
assert serializer.errors['password'][0].code == 'exc_code'
22422261

22432262
@pytest.mark.parametrize('code', (None, 'exc_code',))

0 commit comments

Comments
 (0)