Вложенные маршруты и функция include
Функция include() позволяет определить вложенные маршруты или подмаршруты для некоторого маршрута. Мы уже использовали её в разделе 2.3 "Установка Django и создание проекта HelloWorld", когда подключали наши URL для нашего приложения blog. В качестве параметра она принимает набор маршрутов:
include(pattern_list)
Параметр pattern_list представляет набор вызовов функций path() и/или re_path().
Изменим код наших представлений в файле views.py, на следующие функции:
from django.http import HttpResponse
def index(request):
return HttpResponse("Главная страница")
def products(request):
return HttpResponse("Список товаров")
def new(request):
return HttpResponse("Новые товары")
def top(request):
return HttpResponse("Наиболее популярные товары")
И определим в файле urls.py приложения blog (blog/urls.py) следующие маршруты:
from django.urls import path, include
from blog import views
product_patterns = [
path("", views.products),
path("new/", views.new),
path("top/", views.top),
]
urlpatterns = [
path("", views.index),
path("products/", include(product_patterns)),
]
Здесь в виде переменной product_patterns отдельно определен набор маршрутов, который касается товаров.
Теперь структура нашего сайта следующая:
- http://127.0.0.1:8000
- http://127.0.0.1:8000/products/
- http://127.0.0.1:8000/products/new/
- http://127.0.0.1:8000/products/top/
Для установки этих маршрутов этот список передается в функцию include():
path("products/", include(product_patterns)),
Причем этот список будет ассоциирован с URL шаблоном products/. В этом случае шаблоны вложенных маршрутов будут объединены с шаблоном родительского маршрута, и таким образом будет сформирован общий шаблон, которому должен соответствовать запрос.
Например, если придет запрос http://127.0.0.1:8000/products/top, то он будет обрабатываться функцией top:
Таким образом, мы можем сгруппировать маршруты для запросов, которые начинаются с определенного шаблона. Что также позволяет избежать повтора частей URL шаблона, когда шаблон url начинается с одного и того же сегмента.
То есть если мы возьмем наш главный urls.py проекта, и изменим путь к приложению нашего блога, то ко всем запросам добавится к пути blog
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path("blog/", include("blog.urls")),
]
И теперь адреса будут выглядеть как:
- http://127.0.0.1:8000/blog/
- http://127.0.0.1:8000/blog/products/
- http://127.0.0.1:8000/blog/products/new/
- http://127.0.0.1:8000/blog/products/top/
Получение параметров
Вложенные маршруты получают параметры, определенные в родительских маршрутах. Например, определим в файле views.py следующие функции-представления:
from django.http import HttpResponse
def index(request):
return HttpResponse("Главная страница")
def products(request, id):
return HttpResponse(f"Товар {id}")
def comments(request, id):
return HttpResponse(f"Комментарии о товаре {id}")
def questions(request, id):
return HttpResponse(f"Вопросы о товаре {id}")
Здесь все функции кроме первого параметра request, имеют и второй параметр: id - условный номер товара.
Изменим файл urls.py приложения blog:
from django.urls import path, include
from blog import views
product_patterns = [
path("", views.products),
path("comments/", views.comments),
path("questions/", views.questions),
]
urlpatterns = [
path("", views.index),
path("products/<int:id>/", include(product_patterns)),
]
Здесь для второго маршрута определяется числовой параметр id.
Этот параметр передается всем вложенным маршрутам, соответственно нам не надо определять данный параметр во вложенных маршрутах: