Маршрутизация и функции представления

Курс по Django: https://stepik.org/a/183363

Архив проекта: 04_sitewomen.zip

На прошлом занятии мы подробно рассмотрели общие принципы работы фреймворка Django и создали приложение women. Но пока наш сайт не реагирует ни на какие запросы от пользователей, кроме тестовой главной страницы. Какой должен быть наш следующий шаг? Давайте для начала создадим обработчик главной страницы приложения women с помощью функции представления. Как я уже отмечал, представления в Django можно реализовывать или в виде функций или в виде классов. Но для лучшего понимания механики обработки запросов мы воспользуемся именно функцией. Эта функция будет срабатывать при обращении к главной странице приложения women, называться index и формировать ответ в виде простой строки:

def index(request):
    return HttpResponse("Страница приложения women.")

Здесь указывается первый обязательный параметр request – это ссылка на экземпляр класса HttpRequest, который содержит информацию о запросе, о сессии, куках и так далее. То есть, через переменную request нам доступна вся возможная информация в рамках текущего запроса. На выходе эта функция возвращает экземпляр объекта HttpResponse, который будет автоматически формировать нужный заголовок ответа, а содержимое будет представлено простой строкой.

Теперь нам нужно связать эту функцию представления с соответствующим URL-адресом. Для этого в пакете конфигурации sitewomen откроем файл urls.py и в список адресов urlpatterns добавим новый путь с помощью специальной функции path:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('women/', index),
]

Здесь первый параметр – это суффикс URL-адреса, то есть, часть URL, которая добавляется после доменного имени (при этом в конце принято указывать слеш). Например, если наш сайт располагается по адресу

http://127.0.0.1:8000

то первый аргумент 'women/' добавляется в конце этого пути:

http://127.0.0.1:8000/women/

Именно такой адрес мы сейчас и определяем. Второй аргумент – это ссылка на функцию представления, которая будет автоматически вызываться при срабатывании указанного URL-адреса и возвращать ответ на клиентский запрос. В нашем примере ответ формируется в виде экземпляра класса HttpResponse.

Теперь нам нужно импортировать функцию index, чтобы она была доступна в пакете конфигурации:

from women.views import index

Если интегрированная среда вам здесь указывает ошибку, то это потому, что рабочим каталогом следует указать проект sitewomen.

Проверим работоспособность нашего нового приложения и маршрута. Запустим тестовый веб-сервер:

python manage.py runserver

И откроем страницу:

http://127.0.0.1:8000/women/

В рамках этого приложения мы можем определять сколько угодно таких функций, связанных с разными URL-адресами. Например, пропишем еще одну функцию для отображения списка статей по рубрикам:

def categories(request):
    return HttpResponse("<h1>Статьи по категориям</h1>")

Мы здесь используем тег h1, чтобы браузер отобразил эту строку как заголовок первого уровня. Затем, добавляем еще один путь в список urlpatterns:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('women/', index),
    path('cats/', categories),
]

И делаем импорт нужных функций из модуля views нашего приложения:

from women.views import index, categories

Но это не очень удобно, поэтому на практике поступают так:

from women import views

а, затем, указывают функции, используя имя модуля views:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('women/', views.index),
    path('cats/', views.categories),
]

Все, у нас появился новый URL-адрес:

http://127.0.0.1:8000/cats/

по которому отображается заголовок первого уровня. По аналогии мы можем добавлять самые разные URL в наш сайт.

Обратите внимание, как только мы добавили дополнительные маршруты, тестовая главная страница перестала выдаваться, вместо этого мы видим исключение 404 – страница не найдена. Чтобы задать маршрут для главной страницы, нужно вместо «women/» записать пустую строку:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', views.index),
    path('cats/', views.categories),
]

Здесь пустая строка как раз соответствует маршруту главной страницы, и при обращении к ней будет вызываться функция представления index.

Однако такой подход, когда маршруты приложения прописываются в пакете конфигурации, нарушает принцип независимости приложений. Действительно, если мы захотим перенести приложение women на другой сайт, то нам придется дополнительно копировать все его маршруты, что не очень удобно и хорошо. Как это можно разрешить? Очень просто. Django позволяет вторым параметром вместо функции представления передавать список URL-адресов приложения и связанные с ними функции. Для этого мы сначала импортируем специальную функцию include:

from django.urls import path, include

А, затем, в списке маршрутов с ее помощью подключим список URL уже из нашего приложения women:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('women/', include('women.urls')),
]

Мы здесь в качестве параметра указываем строку, в которой сначала записываем имя приложения и через точку файл urls, где будут прописаны маршруты приложения women. Ну а дальше все просто. Мы добавляем в приложение новый файл urls.py и в нем формируем список urlpatterns:

from django.urls import path
from women import views
 
urlpatterns = [
    path('', views.index),
]

Здесь мы, во-первых, импортируем функцию path, которая и связывает URL c функциями представления и, во-вторых, импортируем модуль views текущего пакета. Далее, в списке urlpatterns вызываем функцию path,  первым параметром указываем пустую строку, а вторым функцию index. Как вы думаете, какому URL-адресу будет соответствовать эта пустая строка? Смотрите, в основном пакете конфигурации у нас указано, что к адресам 'women.urls' следует добавлять суффикс 'women/', то есть, функция index будет соответствовать адресу:

http://127.0.0.1:8000/women/

Поэтому пустая строка в нашем приложении будет ссылаться именно на этот URL-адрес. Давайте проверим. Запустим веб-сервер и откроем эту страницу. Да, мы видим, что отработала именно функция index.

Если же мы добавим еще один маршрут в наш список приложения, например:

urlpatterns = [
    path('', views.index),
    path('cats/', views.categories),
]

То он будет соответствовать URL-адресу:

http://127.0.0.1:8000/women/cats/

Как видите все достаточно просто и при этом мы получили относительную независимость нашего приложения women от основного проекта сайта.

На этом мы завершим начальное рассмотрение построения маршрутов и определения простых функций представления. Далее мы еще вернемся к этой теме и посмотрим, как можно использовать классы в качестве обработчиков запросов, какие дополнительные параметры имеются у функции path и некоторые другие моменты.

Курс по Django: https://stepik.org/a/183363

Видео по теме