Django 5 для начинающих

Прогресс по курсу:  9/1004

2.5 Диспетчер URL, часть 2.
3 из 13 шагов пройдено
0 из 42 баллов  получено

 Вложенные маршруты и функция 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 отдельно определен набор маршрутов, который касается товаров.


Теперь структура нашего сайта следующая:


Для установки этих маршрутов этот список передается в функцию 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")),
]


И теперь адреса будут выглядеть как:

 

Получение параметров

Вложенные маршруты получают параметры, определенные в родительских маршрутах. Например, определим в файле 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.

Этот параметр передается всем вложенным маршрутам, соответственно нам не надо определять данный параметр во вложенных маршрутах:


  • Комментариев
Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий
Комментарий закреплён

Понравилась задача, тест или урок? Поставьте лайк, поддержите курс. Ваша поддержка очень важна для нас.

@Илья_Перминов, Ох, КАК МНЕ НРА! Вот, когда начинаешь понимать, что значит структура и план обучения! Просто супер! И задачи на повторение пройденного материала - нужны новичкам, таким как я, как воздух! Спасибо большое!

Очень надеюсь, что и дальше все будет на таком же уровне! (судя по отзывам о вашем курсе, все будет именно так). Купил сразу 2 ваших курса по Django, все круто!)))

я конечно не буду судить автора за повторяющие слова одни и те же. Вот допустим я описываю функцию include() Функция include() позволяет определить вложенные маршруты или подмаршруты для некоторого маршрута. я бы наверное описал бы это так. 

"Так, давайте разберемся с этой функцией include() в программировании. Это как магия вложенных маршрутов! Ты думаешь, у тебя есть один главный маршрут, но нет! Тут вдруг появляются подмаршруты, как в сказке про луковицу – открываешь один слой, а там еще один, и так до бесконечности вы наверное уже представили хаус из одних маршрутов но не стоит бояться это нормально!

Так вот, эта функция include() – это как магическое слово, которое говорит твоему коду: 'Эй, прикрутите сюда еще парочку маршрутов, чтобы всё было круто и организовано'. Представьте себе, ваш код как набор игральных карт, и вы можете добавить к нему еще карты, чтобы улучшить свою 'руку'!

И вот ты думаешь, что у тебя есть просто дорожка, но нет, тут внезапно появляются всякие боковые пути. Это как вождение по городу – вы на главной дороге, а потом решаете заехать в кафе или парк, и ваш маршрут становится веселее!

Так что, если вы когда-то услышите про функцию include() в программировании, помните, это не просто код – это как искусство встраивания маршрутов, как LEGO для вашего программного мира!" 🚀👾

Изменен Konstantin Chekhovich

@Konstantin_Chekhovich, очень хорошее описание, сразу видно что есть литературный талант. Только он среди программистов довольно редко встречается.

@Дмитрий_Селезнев, Спасибо огромное)

@Konstantin_Chekhovich, очень поэтично, но нереально трудно уловить суть. Меньше слов - меньше читать - быстрее понимание. Ваш длинный текст я бы заменила на  'include - классная штука'. Авторы курса пишут очень хороший, легкий текст.

@Konstantin_Chekhovich, Хорошее описание, но мне такое совсем не по душе, мне больше нравится сухая теория без неуместных аналогий, магии, сказок и прочего, мне нужная четкая теория, правильные термины и корректное их описание (некоторые черезчур сложные моменты, можно описать абстратными примерами, но не так поэтично, все той же терминологией), с практичными примерами, без лишней воды, обычно я ценю больше такой подход)

Если во views.py например функцию comments переписать как:

def comments(request):
    return HttpResponse("Комментарии о товаре")

И при вызове адреса http://127.0.0.1:8000/blog/products/7/comments/ выходит ошибка. 
Почему ошибка?
В urls.py числовой параметр id передаётся лишь products/
К пути comment/ он не имеет отношения

@Антон_Кудряшов, нет, он будет передаваться всем представлениям в списке product_patterns, соответственно любое представление из этого списка будет вызываться с этим параметром, например так: comments(request, id). А так как мы объявили данную функцию без параметра id, то попытка вызвать её с данным параметром приведёт к ошибке, так как функция его не принимает.

Изменен Дмитрий Селезнев

@Антон_Кудряшов, вот кстати подтверждение из документации:

An included URLconf receives any captured parameters from parent URLconfs

https://docs.djangoproject.com/en/5.0/topics/http/urls/#captured-parameters

Спасибо за объяснение! Теперь все понял)

Здесь разве тоже не должен быть прописан /blog/ ? На сколько я понимаю такой адрес http://127.0.0.1:8000 приведет к ошибке, разве нет?

Изменен Максим Михеев

@Максим_Михеев, да, верно, исправил.

 В конце products наверное слэш должен стоять?

@Максим_Михеев, да, спасибо, исправил.

Здравствуйте, это раздел 2.3:

@Максим_Михеев, спасибо, исправил ссылку.

"Причем этот список будет ассоциирован с URL шаблоном product"

Тут должно быть products, или я что-то путаю?)

@Daniil_Nagapetyan, да, спасибо, исправил.