diff --git a/django/utils/text.py b/django/utils/text.py index cb39110b83..4d77ce7f41 100644 --- a/django/utils/text.py +++ b/django/utils/text.py @@ -396,15 +396,15 @@ def slugify(value, allow_unicode=False): Convert to ASCII if 'allow_unicode' is False. Convert spaces or repeated dashes to single dashes. Remove characters that aren't alphanumerics, underscores, or hyphens. Convert to lowercase. Also strip leading and - trailing whitespace. + trailing whitespace, dashes, and underscores. """ value = str(value) if allow_unicode: value = unicodedata.normalize('NFKC', value) else: value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore').decode('ascii') - value = re.sub(r'[^\w\s-]', '', value.lower()).strip() - return re.sub(r'[-\s]+', '-', value) + value = re.sub(r'[^\w\s-]', '', value.lower()) + return re.sub(r'[-\s]+', '-', value).strip('-_') def camel_case_to_spaces(value): diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index dcc354e2e2..921aba5de8 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -853,8 +853,8 @@ appropriate entities. #. Converting to lowercase. #. Removing characters that aren't alphanumerics, underscores, hyphens, or whitespace. - #. Removing leading and trailing whitespace. #. Replacing any whitespace or repeated dashes with single dashes. + #. Removing leading and trailing whitespace, dashes, and underscores. For example:: @@ -867,6 +867,11 @@ appropriate entities. >>> slugify('你好 World', allow_unicode=True) '你好-world' + .. versionchanged:: 3.2 + + In older versions, leading and trailing dashes and underscores are not + removed. + .. _time-zone-selection-functions: ``django.utils.timezone`` diff --git a/docs/releases/3.2.txt b/docs/releases/3.2.txt index a869eb49cf..5436726fa4 100644 --- a/docs/releases/3.2.txt +++ b/docs/releases/3.2.txt @@ -280,6 +280,9 @@ Miscellaneous * :attr:`.ModelAdmin.prepopulated_fields` no longer strips English stop words, such as ``'a'`` or ``'an'``. +* :func:`~django.utils.text.slugify` now removes leading and trailing dashes + and underscores. + .. _deprecated-features-3.2: Features deprecated in 3.2 diff --git a/tests/utils_tests/test_text.py b/tests/utils_tests/test_text.py index 2310c9c2a0..f7a0a807e1 100644 --- a/tests/utils_tests/test_text.py +++ b/tests/utils_tests/test_text.py @@ -195,6 +195,10 @@ class TestUtilsText(SimpleTestCase): (' multiple---dash and space ', 'multiple-dash-and-space', False), ('\t whitespace-in-value \n', 'whitespace-in-value', False), ('underscore_in-value', 'underscore_in-value', False), + ('__strip__underscore-value___', 'strip__underscore-value', False), + ('--strip-dash-value---', 'strip-dash-value', False), + ('__strip-mixed-value---', 'strip-mixed-value', False), + ('_ -strip-mixed-value _-', 'strip-mixed-value', False), ('spam & ıçüş', 'spam-ıçüş', True), ('foo ıç bar', 'foo-ıç-bar', True), (' foo ıç bar', 'foo-ıç-bar', True),