Перенаправления (redirect). Функция reverse

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

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

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

  • 301 – страница перемещена на другой постоянный URL-адрес;
  • 302 – страница перемещена временно на другой URL-адрес.

Функция redirect()

В Django подобные редиректы достаточно просто выполняются с помощью функции:

django.shortcuts.redirect

Давайте для примера сделаем перенаправление со страницы архива, если год больше 2023:

def archive(request, year):
    if year > 2023:
        return redirect('/')
 
    return HttpResponse(f"<h1>Архив по годам</h1><p >{year}</p>")

Здесь в качестве первого параметра указывается страница, на которую происходит перенаправление, в данном случае – это главная страница сайта. Также в файле settings.py вернем прежнее значение параметра DEBUG:

DEBUG = True

Если теперь выполнить запрос:

127.0.0.1:8000/archive/2024/

то мы попадем на главную страницу с кодом перенаправления 302 (см. консоль). Если же нам нужно указать постоянный редирект с кодом 301, то записывается дополнительный параметр:

return redirect('/', permanent=True)

Вообще в качестве первого аргумента функции redirect() можно передавать не только конкретный URL, но и представление. В частности, вместо '/' можно передать ссылку на функцию index следующим образом:

return redirect(index, permanent=True)

В данном случае это будет одно и то же.

Классы HttpResponseRedirect и HttpResponsePermanentRedirect

Фреймворк Django дополнительно поддерживает классы для выполнения перенаправлений. В частности имеются два класса:

  • HttpResponseRedirect – для редиректа с кодом 302;
  • HttpResponsePermanentRedirect – для редиректа с кодом 301

которые можно использовать вместо функции redirect() следующим образом:

def archive(request, year):
    if year > 2023:
        return HttpResponseRedirect('/')
 
    return HttpResponse(f"<h1>Архив по годам</h1><p >{year}</p>")

На самом деле функция redirect() использует в своей работе эти классы, но, вместе с тем, она несколько более гибкая. Поэтому какой вариант выбирать решает сам программист, исходя из логики построения кода.

Параметр name функции path

Однако указывать в функции redirect, да и вообще где бы то ни было в приложении конкретный URL-адрес (кроме их списка в коллекции urlpatterns) – это порочная практика, или, как еще говорят – хардкодинг. Вместо этого каждому шаблону пути можно присвоить свое уникальное имя и использовать его в рамках всего проекта.

Давайте определим имена для наших URL-запросов. Для этого перейдем в файл women/urls.py и в каждой функции path пропишем параметр name с уникальными именами:

urlpatterns = [
    path('', views.index, name='home'),
    path('cats/<slug:cat_slug>/', views.categories_by_slug, name='cats'),
    path('cats/<int:cat_id>/', views.categories, name='cats_id'),
    re_path(r'^archive/(?P<year>[0-9]{4})/', views.archive, name='archive'),
]

Конечно, эти имена вы можете выбрать и другие – это лишь пример. И далее, в функции redirect мы можем выполнить перенаправление на главную страницу, указав имя home:

return redirect('home', permanent=True)

Как видите, это гораздо понятнее и безопаснее использования конкретных URL-адресов. Если в дальнейшем маршрут изменится, то автоматически изменится и адрес перенаправления для home.

Функция reverse()

Если же маршрут помимо имени содержит еще параметры, как например, маршрут ‘cats’ с параметром slug, то для корректного перенаправления необходимо в функции redirect() вторым и последующими аргументами передать требуемые параметры. В нашем случае это можно сделать так:

return redirect('cats', 'music')

В результате, функция redirect() вычислит следующий URL:

http://127.0.0.1:8000/cats/music/

и сделает на него перенаправление.

Но мы можем разделить операции вычисления URL и непосредственно перенаправление. Для этого в Django имеется функция:

django.urls.reverse()

которая возвращает строку URL-адреса, вычисленный на основе переданного имени и набора аргументов. Например, для вычисления адреса маршрута cats с параметром ‘music’ функцию reverse() можно вызвать следующим образом:

url_redirect = reverse('cats', args=('music', ))

А, затем, передать этот маршрут в функцию reverse():

return redirect(url_redirect)

или в соответствующий класс:

return HttpResponsePermanentRedirect(url_redirect)

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

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

Видео по теме