1.4. Контроллер-функции и маршрутизация

Контроллер Django — это код, запускаемый при обращении по интернет-адресу определенного формата и в ответ выводящий на экран определенную веб-страницу.

В документации по Django используется термин View (вид, или представление). Здесь будем использовать термин Controller (контроллер) [см. раздел О Django]

Контроллер Django может представлять собой как функцию, так и класс. Первые более универсальны, но зачастую трудоемки в программировании, вторые позволяют выполнить типовые задачи, наподобие вывода списка каких-либо позиций, минимумом кода.

Для хранения кода контроллеров изначально предназначается модуль views.py, создаваемый в каждом пакете приложения.

Создание контроллер-функции

Напишем контроллер-функцию, которая будет выводить строку Hello world!. Для этого откроем модуль views.py пакета приложения firstapp, заменим его содержимое следующим кодом:

from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello world!")

Здесь мы импортируем класс HttpResponse из стандартного пакета django.http.

Затем определяем функцию index(), которая в качестве единственного обязательного параметра получает экземпляр класса HttpRequest, хранящий различные сведения о полученном запросе: запрашиваемый интернет-адрес, данные, полученные от посетителя, служебную информацию от самого веб-обозревателя и пр. По традиции его называют request. В нашем случае мы его не используем.

В теле функции мы создаем экземпляр класса HttpResponse. Он будет представлять ответ, отправляемый клиенту. Содержимое этого ответа — текстовое сообщение — указываем единственным параметром конструктора этого класса. Готовый экземпляр класса возвращаем в качестве результата.

Создание маршрута

Если мы попробуем запустить отладочный веб-сервер на этом этапе, то мы получим вновь стартовый экран пустого Django проекта:

Это произошло потому, что нигде не связали нашу написанную контроллер-функцию с интернет-адресом.

Откроем файл urls.py, находящийся в пакете конфигурации firstsite. Увидим в нём следующий код:

from django.contrib import admin
from django.urls import path

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

Здесь можно заметить список маршрутов urlpatterns. Каждый маршрут представляется в виде результата, возвращаемого функцией path() из django.urls. В качестве параметров она принимает строку с шаблонным путем и ссылку на контроллер.

В качестве второго параметра функции path() также можно передать список маршрутов уровня приложения. Этот вариант как раз демонстрируется в единственном маршруте нашего списка маршрутов.

Добавим в список новый маршрут, связывающий шаблонный путь firstapp/ и контроллер-функцию index(). Для чего изменим код следующим образом:

from django.contrib import admin
from django.urls import path
from firstapp.views import index

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

Сохраним изменения, запустим наш проект и перейдем по адресу http://127.0.0.1:8000/firstapp/:

Создание маршрутов с использованием функции include():

Создавая более сложный сайт, наше количество маршрутов вырастет до таких размеров, что мы просто запутаемся в них. Именно поэтому будем формировать списки маршрутов рекомендуемым создателями Django образом.

Маршрутизатор Django при просмотре списка маршрутов не требует, чтобы путь, полученный из клиентского запроса (реальный), и шаблонный путь, записанный в очередном маршруте, совпадали полностью. Достаточно лишь того факта, что шаблонный путь совпадает с началом реального.

Как было сказано ранее, функция path() позволяет указать во втором параметре вместо ссылки на контроллер-функцию другой, вложенный, список маршрутов. В таком случае маршрутизатор, найдя совпадение, удалит из реального пути его начальную часть (префикс), совпавшую с шаблонным путем, и приступит к просмотру маршрутов из вложенного списка, используя для сравнения реальный путь уже без префикса.

Исходя из всего этого, мы можем создать иерархию списков маршрутов. В списке из пакета конфигурации (списке маршрутов уровня проекта) запишем маршруты, которые указывают на вложенные списки маршрутов, принадлежащие отдельным приложениям (списки маршрутов уровня приложения). А в последних непосредственно запишем нужные контроллеры.

Начнем со списка маршрутов уровня приложения firstapp. Создадим в пакете этого приложения файл urls.py и напишем следующее:

from django.urls import path
from .views import index

urlpatterns = [
    path('', index),
]

И, наконец, исправим код модуля urls.py из пакета конфигурации:

from django.contrib import admin
from django.urls import path, include

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

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

Как только наш сайт получит запрос с интернет-адресом http://localhost:8000/firstapp/, маршрутизатор обнаружит, что присутствующий в нем путь совпадает с шаблонным путем firstapp/, записанным в urls.py из пакета конфигурации. Он удалит из реального пути префикс, соответствующий шаблонному пути, и получит новый путь — пустую строку. Этот путь совпадет с единственным маршрутом из вложенного списка, в результате чего запустится записанный в этом маршруте контроллер-функция index(), и на экране появится уже знакомое нам текстовое сообщение.

Last updated