В прошлой теме рассматривалось сопоставление адресов URL и функций, которые обрабатывают запросы по этим адресам. Например, у нас есть следующие функции в файле views.py:
from django.http import HttpResponse
def index(request):
return HttpResponse("<h2>Главная</h2>")
def about(request):
return HttpResponse("<h2>О сайте</h2>")
def contact(request):
return HttpResponse("<h2>Контакты</h2>")
Это так называемые функции-представления или view function. И в файле urls.py проекта они сопоставляются с адресами URL с помощью функции path():
from django.urls import path
from hello import views
urlpatterns = [
path('', views.index),
path('about', views.about),
path('contact', views.contact),
]
За сопоставление путей и функций-представлений отвечает функция path(), которая располагается в пакете django.urls и которая принимает четыре параметра:
path(route, view, kwargs=None, name=None)
route: представляет шаблон адреса URL, которому должен соответствовать запрос
view: функция-представление, которое обрабатывает запрос
kwargs: дополнительные аргументы, которые передаются в функцию-представление
name: название маршрута
В примере выше применялись только первые два параметра, которые являются обязательными: запрошенный адрес URL и функция, которая обрабатывает запрос по этому адресу. Дополнительно через третий параметр можно указать имя маршрута:
path('', views.index, name='home'),
В данном случае маршрут будет называться "home".
Хотя мы можем успешно применять функцию path() для определения маршрутов, она довольно ограничена по своему действию. Запрошенный путь должен в точности соответствовать указанному в маршруте адресу URL. Так, в примере выше чтобы функция views.about могла обрабатывать запрос, адрес должен быть в точности "about". Например, стоит нам указать слеш в конце: "about/" и django уже не сможет сопоставить путь с запросом.
В качестве альтернативы для определения маршрутов мы можем использовать функцию re_path(), которая также располагается в пакете django.urls и имеет тот же набор параметров:
re_path(route, view, kwargs=None, name=None)
Ее преимущесто состоит в том, что она позволяет задать адреса URL с помощью регулярных выражений.
Например, изменим определение файла urls.py следующим образом:
from django.urls import path, re_path
from hello import views
urlpatterns = [
path('', views.index),
re_path(r'^about', views.about),
re_path(r'^contact', views.contact),
]
Адрес в первом маршруте по-прежнему образуется с помощью функции path и указывает на корень веб-приложения.
Остальные два маршрута образуются с помощью функции re_path(). Причем, поскольку определяется регуляное выражение, то перед строкой с шаблоном
адреса URL ставится буква r. В самом шаблоне адреса можно использовать различные элементы синтаксиса регулярных выражений.
В частности, выражение ^about указывает, что адрес должен начинаться с "about". Однако он необязательно в точности должен соответствовать
строке "about", как это было в случае с функцией path.
Например, мы можем обратиться по любому адресу, главное чтобы он начинался с "about", и тогда подобный запрос будет обрабатываться функцией views.about.
Когда запрос приходит к приложению, то система проверяет соответствие запроса маршрутам по мере их определения: вначале сравнивается первый маршрут, если он не подходит, то сравнивается второй и так далее. Поэтому более общие маршруты должны определяться в последнюю очередь, а более конкретные маршруты должны идти в начале. Например:
from django.urls import path, re_path
from hello import views
urlpatterns = [
re_path(r'^about/contact/', views.contact),
re_path(r'^about', views.about),
path('', views.index),
]
В данном случае адрес "^about/contact" представляет более конкретный маршрут по сравнению c "^about". Поэтому он определяется в первую очередь.
Если бы было наоборот:
urlpatterns = [
path('', views.index),
re_path(r'^about', views.about),
re_path(r'^about/contact', views.contact),
]
то запрос по адресу "about/contact" обрабатывался бы функцией views.about
Некоторые базовые элементы регуляных выражений, которые можно использовать для определения адресов URL:
^(начало адреса)
$(конец адреса)
+(1 и более символов)
?(0 или 1 символ)
{n}(n символов)
{n, m}(от n до m символов)
.(любой символ)
\d+(одна или несколько цифр)
\D+(одна или несколько НЕ цифр)
\w+(один или несколько буквенных символов)
Рассмотрим несколько возможных сопоставлений шаблонов адресов и запросов:
Адрес | Запрос |
r'^$' | http://127.0.0.1/ (корень сайта) |
r'^about' | http://127.0.0.1/about/ или http://127.0.0.1/about/contact |
r'^about/contact' | http://127.0.0.1/about/contact |
r'^products/\d+/' | http://127.0.0.1/products/23/ или http://127.0.0.1/products/6459/abc Но не соответствует запросу http://127.0.0.1/products/abc/ |
r'^products/\D+/' | http://127.0.0.1/products/abc/ или http://127.0.0.1/products/abc/123 Не соответствует запросу http://127.0.0.1/products/123/ или http://127.0.0.1/products/123/abc |
r'^products/phones|tablets/' | http://127.0.0.1/products/phones/1 или http://127.0.0.1/products/tablets/ Не соответствует запросу http://127.0.0.1/products/clothes/ |
r'^products/\w+' | http://127.0.0.1/products/abc/ или http://127.0.0.1/products/123/ Не соответствует запросу http://127.0.0.1/products/abc-123 |
r'^products/[-\w]+/' | http://127.0.0.1/products/abc-123 |
r'^products/[A-Z]{2}/' | http://127.0.0.1/products/RU Не соответствует запросам http://127.0.0.1/products/Ru или http://127.0.0.1/products/RUS |
Выше были рассмотрены все параметры функций path и re_path, кроме одного - kwargs, который позволяет передать в функцию-представление
некоторые значения. Например, в файле views.py определим следующие функции:
from django.http import HttpResponse
def index(request):
return HttpResponse("Главная
")
def about(request, name, age):
return HttpResponse(f"""
О пользователе
Имя: {name}
Возраст: {age}
""")
Здесь функция about() также принимает два дополнительных параметра: name и age (условно имя и возраст пользователя). В функции
их значения отправляются пользователю вместе с остальным содержимым.
Изменим файл urls.py:
from django.urls import path
from hello import views
urlpatterns = [
path('', views.index),
path('about', views.about, kwargs={"name":"Tom", "age": 38}),
]
С помощью параметра kwargs в функцию about передается словарь с двумя значениями - для двух параметров функции. Соответственно при обращении к этой функции мы увидим в браузере соответствующие данные: