diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 9b922ed918..bc0d4be12b 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -799,7 +799,7 @@ def __init__(self, allow_unicode=False, **kwargs): if self.allow_unicode: validator = RegexValidator(re.compile(r'^[-\w]+\Z', re.UNICODE), message=self.error_messages['invalid_unicode']) else: - validator = RegexValidator(re.compile(r'^[-a-zA-Z0-9_]+$'), message=self.error_messages['invalid']) + validator = RegexValidator(re.compile(r'^[-a-zA-Z0-9_]+\Z'), message=self.error_messages['invalid']) self.validators.append(validator) diff --git a/tests/test_fields.py b/tests/test_fields.py index 4cbbc030e3..f55d3e4bf0 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -983,6 +983,14 @@ class TestSlugField(FieldValues): outputs = {} field = serializers.SlugField() + def test_trailing_newline_is_invalid(self): + # `$` would also match before a trailing newline; Django's own slug + # validators reject it. + for allow_unicode in (False, True): + field = serializers.SlugField(allow_unicode=allow_unicode, trim_whitespace=False) + with pytest.raises(serializers.ValidationError): + field.run_validation('slug-99\n') + def test_allow_unicode_true(self): field = serializers.SlugField(allow_unicode=True)