Блог хеллоуворлдщика

Slash в конце пути URL в Django

28.01.2026 slash, url, django, python

Как многим известно, Django из коробки принуждает использовать рекомендацию по добавлению слэша (/) в конце пути URL, что нравится далеко не всем. Я лично нахожу это устаревшей SEO практикой, которая абсолютно потеряла свой смысл, и хоть как-то влиет на релеватность поисковой выдачи. Поисковые алгоритмы за эти десятилетия изменились кардинально, а добровольно-принудительная практика добавления слэша в конце пути URL в Django осталась. Да и в целом мне просто это не нравится практически и эстетически. Так уж сложилась практика ввода адреса URL, что данный слэш никому не нужен от слова совсем.

Сам фреймворк Django разрешает не использовать завершающий слэш в пути URL, если вы будете писать маршруты соответствующим образом, т.е. просто ставить слэш, где он вам нужен, а не каждый раз в конце его маршрута. Но если использовать коробочные решения, вроде django-debug-toolbar или django.contrib.admin, где все маршруты уже прописаны за вас, то там слэш будет явно и жестко добавлен в конце каждого маршрута, и избавиться от него каким-то параметром конфига нельзя, потому что такого конфига просто нет.

Существующие официальное решение по избавлению от завершающего слэша через APPEND_SLASH для django-debug-toolbar или django.contrib.admin в пути URL полностью проблему не решают. Конфигурационный параметр APPEND_SLASH может только включать или отключать редирект, если путь URL был передан без завершающего слэша. В купе с Nginx и APPEND_SLASH = False можно добиться работы без завершающего слэша, но создание/генерация маршрутов внутри приложения по-прежнему будут его добавлять, а нам-то нужно, чтобы его не было везде. Единственное решение, которое я нашел для себя обоснованным, это тупо пересоздать маршруты без завершиющего слэша, где этот слэш был добавлен. Решение, возможно, не самое лучшее, но задачу выполняет. Другого я, к сожалению, найти не смог. Собственно, решение изложено ниже.

Первое и самое необходимое, нам нужно установить параметр APPEND_SLASH в значение False, чтобы роутинг Django не добавлял завершающий слэш в конец пути URL.

# djangoproject/settings.py

APPEND_SLASH = False

Второе и последнее, точечно переписать маршруты, которые содержат завершающий слэш. В моем примере учитываются только пакет django-debug-toolbar и приложение django.contrib.admin. Если вы используете еще что-то, то возможно потребуется внести правки в сниппет, т.к. данное решение не универсальное, а заточено только под вышесказанное.

# djangoproject/urls.py

from django.contrib import admin
from django.urls import path
from django.urls.resolvers import RoutePattern, RegexPattern, URLPattern, URLResolver
from django.conf import settings


def _make_no_trailing_slash_pattern(pattern, prefix='/'):
    if isinstance(pattern, RoutePattern):
        route: str = pattern._route.strip('/')
        if route != '':
            route = prefix + route
        return RoutePattern(route, pattern.name, pattern._is_endpoint)
    elif isinstance(pattern, RegexPattern):
        regex: str = pattern._regex.strip('/')
        if regex.startswith('^'):
            regex = '^' + prefix + regex.removeprefix('^')
        else:
            regex = prefix + regex
        if regex.endswith('/$'):
            regex = regex.removesuffix('/$') + '$'
        return RegexPattern(regex, pattern.name, pattern._is_endpoint)
    else:
        raise ValueError('The pattern type of "' + type(pattern).__name__ + '" is not supported.')


def _make_no_trailing_slash_urls(urls, is_root=True):
    if not isinstance(urls, list):
        return urls

    result = []
    for url in urls:
        if isinstance(url, URLPattern):
            result.append(
                URLPattern(
                    _make_no_trailing_slash_pattern(url.pattern, '' if is_root else '/'),
                    url.callback,
                    url.default_args,
                    url.name,
                )
            )
        elif isinstance(url, URLResolver):
            result.append(
                URLResolver(
                    _make_no_trailing_slash_pattern(url.pattern, '' if is_root else '/'),
                    _make_no_trailing_slash_urls(url.url_patterns, False),
                    url.default_kwargs,
                    url.app_name,
                    url.namespace,
                )
            )
        else:
            raise ValueError('The route type of "' + type(url).__name__ + '" is not supported.')

    return result


urlpatterns = [
    path(
        'admin',
        [_make_no_trailing_slash_urls(admin.site.urls[0], False), *admin.site.urls[1:]],
    ),
]

if settings.ENABLE_DEBUG_TOOLBAR:
    from debug_toolbar.toolbar import debug_toolbar_urls

    urlpatterns += _make_no_trailing_slash_urls(debug_toolbar_urls())


# Ваши маршруты приложения.
urlpatterns += [
    path('yourapp', include('yout.app.urls')),
]

Я буду стараться актуализировать данный сниппет какое-то время, пока у меня будет такая возможность. На текущий момент он протестирован под django==6.0.2 и django-debug-toolbar==6.2.0.