Skip to content

Latest commit

 

History

History
235 lines (159 loc) · 10.2 KB

File metadata and controls

235 lines (159 loc) · 10.2 KB

Модуль 1. Урок 6. Перенаправления (redirect) и функция reverse

В процессе работы нашего проекта cinemahub мы всё чаще сталкиваемся с ситуацией, когда пользователю нужно перенаправить запрос на другую страницу.

Например:

  • пользователь открыл несуществующий фильм — его стоит перенаправить на страницу со списком всех фильмов;
  • после добавления фильма — на страницу с этим фильмом;
  • после удаления фильма — обратно на главную.

В Django есть несколько способов сделать перенаправление, и сегодня мы познакомимся с основными из них.


Что такое перенаправление

Перенаправление (redirect) — это ответ сервера, который сообщает браузеру:

"Эта страница находится по другому адресу, перейди туда."

Браузер получает код ответа (обычно 302 или 301) и автоматически делает новый запрос по указанному адресу.


Перенаправления с помощью функции redirect()

Самый простой способ сделать редирект — использовать встроенную функцию Django redirect().

Пример 1. Перенаправление на главную страницу

from django.shortcuts import redirect
from django.http import HttpResponse

def archive(request, year):
    if year > 2024:
        return redirect('/')  # Перенаправляем на главную страницу
    return HttpResponse(f"<h1>Архив фильмов за {year} год</h1>")

Если ввести в браузере:

http://127.0.0.1:8000/archive/2026/

Браузер автоматически перейдёт на главную страницу cinemahub. Попробуйте изменить год в адресе — увидите, как работает редирект.


Пример 2. Постоянный редирект (permanent=True)

Иногда нужно сообщить браузеру, что адрес страницы навсегда изменился. Для этого используется параметр permanent=True.

def archive(request, year):
    if year > 2024:
        return redirect('/', permanent=True)  # Код 301
    return HttpResponse(f"<h1>Архив фильмов за {year} год</h1>")

Код 301 сообщает браузеру и поисковикам, что страница перенесена навсегда. Для большинства случаев достаточно временного (302) редиректа — именно его Django использует по умолчанию.


Пример 3. Перенаправление на другое представление

Функция redirect() может перенаправлять не только по URL, но и на функцию-представление.

from .views import index

def archive(request, year):
    if year > 2024:
        return redirect(index)  # Перенаправляем на представление index
    return HttpResponse(f"<h1>Архив фильмов за {year} год</h1>")

Это удобно, когда вы хотите избежать «жёстких» ссылок и привязаться к логике проекта.


Работа с именами маршрутов (name в urls.py)

Часто при разработке мы используем имена маршрутов, чтобы не зависеть от структуры URL. В Django это делается через параметр name в файле urls.py.

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='home'),
    path('films/<slug:slug>/', views.show_film, name='film_detail'),
    path('archive/<int:year>/', views.archive, name='archive'),
]

Теперь в redirect() можно указывать имя маршрута, а не сам путь:

def archive(request, year):
    if year > 2024:
        return redirect('home')  # Перенаправление по имени маршрута
    return HttpResponse(f"<h1>Архив фильмов за {year} год</h1>")

Преимущество этого подхода в том, что если вы потом измените URL в urls.py, редирект продолжит работать, ведь он опирается на имя, а не на строку пути.


HttpResponseRedirect и HttpResponsePermanentRedirect

Функция redirect() — это просто удобная оболочка. Внутри она использует классы:

  • HttpResponseRedirect — для временного перенаправления (код 302);
  • HttpResponsePermanentRedirect — для постоянного (код 301).

Пример

from django.http import HttpResponseRedirect

def archive(request, year):
    if year > 2024:
        return HttpResponseRedirect('/')  # временный редирект
    return HttpResponse(f"<h1>Архив фильмов за {year} год</h1>")

На практике вы почти всегда будете использовать именно redirect(), потому что она проще и гибче.


Функция reverse(): получение URL по имени маршрута

Часто нам нужно не просто перенаправить, а сначала вычислить URL по имени маршрута, чтобы вставить его в ссылку, шаблон или редирект.

Для этого используется функция reverse().


Пример: использование reverse()

from django.urls import reverse
from django.http import HttpResponseRedirect

def archive(request, year):
    if year > 2024:
        url = reverse('film_detail', args=('interstellar',))  # вычисляем URL по имени маршрута
        return HttpResponseRedirect(url)
    return HttpResponse(f"<h1>Архив фильмов за {year} год</h1>")

Функция reverse('film_detail', args=('interstellar',)) вернёт строку:

/films/interstellar/

То есть Django сам подставит правильный путь по имени маршрута. Если вы измените URL в urls.py, ничего ломаться не будет — reverse() всегда вычислит актуальный адрес.


Проверка результата

Чтобы увидеть, как работает редирект:

  1. Запустите локальный сервер:

    python manage.py runserver
  2. Откройте в браузере адрес:

    http://127.0.0.1:8000/archive/2026/
    
  3. Если редирект сработал — вы окажетесь на главной странице или на странице фильма (в зависимости от примера).

  4. Попробуйте изменить год и посмотреть разницу.


Как это выглядит в браузере

При выполнении редиректа вы не увидите кода 302 прямо в браузере, но можете открыть Инструменты разработчика (F12 → Network) и увидеть, что первый запрос получил статус 302, а браузер сделал новый запрос по другому адресу.


Практика

  1. Создайте представление redirect_to_random, которое случайным образом выбирает фильм из списка и перенаправляет на его страницу.
  2. Добавьте маршрут для этого представления.
  3. Проверьте работу в браузере.
  4. Попробуйте переделать код, чтобы вместо redirect() использовать reverse().

Важный совет

Когда проект становится крупнее, никогда не используйте “жёсткие” пути (например, redirect('/films/')). Используйте redirect('route_name') или reverse('route_name'). Так ваш код будет гибким и не сломается при изменении структуры URL.


Вопросы для закрепления

  1. Что такое перенаправление (redirect) и зачем оно нужно?
  2. Чем отличается временный редирект (302) от постоянного (301)?
  3. Какая функция в Django используется для перенаправлений?
  4. Зачем использовать параметр name в urls.py?
  5. Чем redirect() отличается от HttpResponseRedirect?
  6. Что делает функция reverse() и зачем она нужна?
  7. Как проверить, что редирект сработал, в браузере?
  8. Что произойдёт, если изменить URL в urls.py, но использовать редирект по имени маршрута?
  9. Как можно использовать reverse() совместно с redirect()?
  10. Почему важно избегать “жёстких” ссылок в Django?

Предыдущий урок | Следующий урок