Диспетчер URL, часть 1
Что делает диспетчер URL
Когда приходит запрос на /blog/posts/5/, Django должен решить, какую функцию вызвать. Этим занимается диспетчер URL (URL dispatcher). Он берёт путь из запроса и по очереди сравнивает его с шаблонами из списка urlpatterns. Первое совпадение побеждает — вызывается связанная с ним view. Если совпадений нет — ответ 404.
Отправная точка указана в settings.py:
ROOT_URLCONF = "config.urls"
Функция path()
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("about/", views.about, name="about"),
path("contacts/", views.contacts, name="contacts"),
]
Аргументы path(route, view, kwargs=None, name=None):
- route — шаблон пути без начального слеша:
"about/", а не"/about/". - view — функция (передаём саму функцию, а не результат её вызова:
views.about, без скобок). - name — имя маршрута. По нему можно строить ссылки, не прописывая адрес вручную (об этом — во второй части).
Слеш в конце
По соглашению Django адреса заканчиваются на /. Если пользователь откроет /about, Django автоматически перенаправит его на /about/ (настройка APPEND_SLASH = True).
Параметры в адресе
Часто часть адреса — переменная: id поста, слаг статьи, имя пользователя. Её заключают в угловые скобки:
urlpatterns = [
path("posts/<int:pk>/", views.post_detail, name="post_detail"),
path("users/<str:username>/", views.profile, name="profile"),
]
Django передаст значение во view именованным аргументом:
def post_detail(request, pk):
return HttpResponse(f"Пост номер {pk}")
def profile(request, username):
return HttpResponse(f"Профиль {username}")
Конвертеры путей
Часть до двоеточия — конвертер. Он проверяет формат и преобразует тип:
| Конвертер | Что принимает | Тип во view | Пример |
|---|---|---|---|
str |
любые символы, кроме / (по умолчанию) |
str |
<str:name> или <name> |
int |
ноль и положительные целые | int |
<int:pk> |
slug |
латиница, цифры, - и _ |
str |
<slug:slug> |
uuid |
UUID | uuid.UUID |
<uuid:id> |
path |
любые символы, включая / |
str |
<path:file_path> |
path("archive/<int:year>/<int:month>/", views.archive)
# /archive/2026/3/ → archive(request, year=2026, month=3)
Обратите внимание: year придёт уже как int, приводить тип вручную не нужно.
include(): маршруты приложений
Держать все маршруты в одном файле неудобно. Поэтому у каждого приложения свой urls.py, а главный файл их подключает:
# config/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
path("blog/", include("blog.urls")),
path("shop/", include("shop.urls")),
path("", include("pages.urls")),
]
# blog/urls.py
urlpatterns = [
path("", views.post_list, name="post_list"), # /blog/
path("<int:pk>/", views.post_detail, name="post_detail"), # /blog/5/
]
include() «отрезает» совпавшую часть (blog/) и передаёт остаток во вложенный список. Поэтому приложение не знает, под каким префиксом его подключили, — и его легко переиспользовать.
Порядок маршрутов важен
urlpatterns = [
path("posts/<str:slug>/", views.post_by_slug),
path("posts/new/", views.post_create), # никогда не сработает!
]
Адрес /posts/new/ совпадёт с первым шаблоном (slug="new"). Конкретные маршруты ставят выше общих.
Итог
- Диспетчер перебирает
urlpatternsсверху вниз, первое совпадение вызывает view. path("route/", view, name="...")— маршрут без начального слеша.- Параметры:
<конвертер:имя>, значение приходит во view именованным аргументом. include()подключает маршруты приложений.
Практика решено 0 из 6
Какая настройка указывает Django, с какого файла начинать поиск маршрутов?
Маршрут path("posts/<int:pk>/", views.post_detail). Какой адрес ему не соответствует?
Напишите view article_detail, которая принимает из URL параметр slug
и возвращает HttpResponse с текстом Статья: <slug> (используйте f-строку).
from django.http import HttpResponse
def article_detail(request, slug):
return HttpResponse(f"Статья: {slug}")
Добавьте в urlpatterns маршрут для адресов вида /articles/moy-pervyj-post/,
который вызывает views.article_detail и передаёт параметр slug. Имя маршрута — article_detail.
urlpatterns = [
path("articles/", views.article_list, name="article_list"),
path("articles/<slug:slug>/", views.article_detail, name="article_detail"),
]
Какие конвертеры путей встроены в Django?
Какую функцию из django.urls используют, чтобы подключить маршруты приложения к главному urls.py?
Войдите, чтобы отмечать пройденные уроки.