Skip to content

Commit 79b2350

Browse files
michael-ktomchristie
authored andcommitted
[fields] Format error message only if params exist (#6624)
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 #6622
1 parent 7179ea9 commit 79b2350

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
@@ -231,12 +231,12 @@ def get_error_detail(exc_info):
231231
error_dict = exc_info.error_dict
232232
except AttributeError:
233233
return [
234-
ErrorDetail(error.message % (error.params or ()),
234+
ErrorDetail((error.message % error.params) if error.params else error.message,
235235
code=error.code if error.code else code)
236236
for error in exc_info.error_list]
237237
return {
238238
k: [
239-
ErrorDetail(error.message % (error.params or ()),
239+
ErrorDetail((error.message % error.params) if error.params else error.message,
240240
code=error.code if error.code else code)
241241
for error in errors
242242
] 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
@@ -2255,14 +2255,33 @@ class ExampleSerializer(serializers.Serializer):
22552255
password = serializers.CharField()
22562256

22572257
def validate_password(self, obj):
2258-
err = DjangoValidationError('exc_msg', code='exc_code')
2258+
err = DjangoValidationError(
2259+
'exc_msg %s', code='exc_code', params=('exc_param',),
2260+
)
22592261
if use_list:
22602262
err = DjangoValidationError([err])
22612263
raise err
22622264

22632265
serializer = ExampleSerializer(data={'password': 123})
22642266
serializer.is_valid()
2265-
assert serializer.errors == {'password': ['exc_msg']}
2267+
assert serializer.errors == {'password': ['exc_msg exc_param']}
2268+
assert serializer.errors['password'][0].code == 'exc_code'
2269+
2270+
@pytest.mark.parametrize('use_list', (False, True))
2271+
def test_validationerror_code_with_msg_including_percent(self, use_list):
2272+
2273+
class ExampleSerializer(serializers.Serializer):
2274+
password = serializers.CharField()
2275+
2276+
def validate_password(self, obj):
2277+
err = DjangoValidationError('exc_msg with %', code='exc_code')
2278+
if use_list:
2279+
err = DjangoValidationError([err])
2280+
raise err
2281+
2282+
serializer = ExampleSerializer(data={'password': 123})
2283+
serializer.is_valid()
2284+
assert serializer.errors == {'password': ['exc_msg with %']}
22662285
assert serializer.errors['password'][0].code == 'exc_code'
22672286

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

0 commit comments

Comments
 (0)