[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:
6866c91b63/django/core/exceptions.py (L168-L169)

Fixes encode/django-rest-framework#6622
This commit is contained in:
Michael 2019-07-01 12:28:16 +00:00 committed by Tom Christie
parent 7179ea9984
commit 79b2350b54
2 changed files with 23 additions and 4 deletions

View File

@ -231,12 +231,12 @@ def get_error_detail(exc_info):
error_dict = exc_info.error_dict
except AttributeError:
return [
ErrorDetail(error.message % (error.params or ()),
ErrorDetail((error.message % error.params) if error.params else error.message,
code=error.code if error.code else code)
for error in exc_info.error_list]
return {
k: [
ErrorDetail(error.message % (error.params or ()),
ErrorDetail((error.message % error.params) if error.params else error.message,
code=error.code if error.code else code)
for error in errors
] for k, errors in error_dict.items()

View File

@ -2255,14 +2255,33 @@ class TestValidationErrorCode:
password = serializers.CharField()
def validate_password(self, obj):
err = DjangoValidationError('exc_msg', code='exc_code')
err = DjangoValidationError(
'exc_msg %s', code='exc_code', params=('exc_param',),
)
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': ['exc_msg exc_param']}
assert serializer.errors['password'][0].code == 'exc_code'
@pytest.mark.parametrize('use_list', (False, True))
def test_validationerror_code_with_msg_including_percent(self, use_list):
class ExampleSerializer(serializers.Serializer):
password = serializers.CharField()
def validate_password(self, obj):
err = DjangoValidationError('exc_msg with %', 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 with %']}
assert serializer.errors['password'][0].code == 'exc_code'
@pytest.mark.parametrize('code', (None, 'exc_code',))