В процессе работы нашего проекта cinemahub мы всё чаще сталкиваемся с ситуацией, когда пользователю нужно перенаправить запрос на другую страницу.
Например:
- пользователь открыл несуществующий фильм — его стоит перенаправить на страницу со списком всех фильмов;
- после добавления фильма — на страницу с этим фильмом;
- после удаления фильма — обратно на главную.
В Django есть несколько способов сделать перенаправление, и сегодня мы познакомимся с основными из них.
Перенаправление (redirect) — это ответ сервера, который сообщает браузеру:
"Эта страница находится по другому адресу, перейди туда."
Браузер получает код ответа (обычно 302 или 301) и автоматически делает новый запрос по указанному адресу.
Самый простой способ сделать редирект — использовать встроенную функцию Django redirect().
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.
Попробуйте изменить год в адресе — увидите, как работает редирект.
Иногда нужно сообщить браузеру, что адрес страницы навсегда изменился.
Для этого используется параметр permanent=True.
def archive(request, year):
if year > 2024:
return redirect('/', permanent=True) # Код 301
return HttpResponse(f"<h1>Архив фильмов за {year} год</h1>")Код 301 сообщает браузеру и поисковикам, что страница перенесена навсегда.
Для большинства случаев достаточно временного (302) редиректа — именно его Django использует по умолчанию.
Функция redirect() может перенаправлять не только по URL, но и на функцию-представление.
from .views import index
def archive(request, year):
if year > 2024:
return redirect(index) # Перенаправляем на представление index
return HttpResponse(f"<h1>Архив фильмов за {year} год</h1>")Это удобно, когда вы хотите избежать «жёстких» ссылок и привязаться к логике проекта.
Часто при разработке мы используем имена маршрутов, чтобы не зависеть от структуры 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,
редирект продолжит работать, ведь он опирается на имя, а не на строку пути.
Функция 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(),
потому что она проще и гибче.
Часто нам нужно не просто перенаправить, а сначала вычислить URL по имени маршрута, чтобы вставить его в ссылку, шаблон или редирект.
Для этого используется функция 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() всегда вычислит актуальный адрес.
Чтобы увидеть, как работает редирект:
-
Запустите локальный сервер:
python manage.py runserver
-
Откройте в браузере адрес:
http://127.0.0.1:8000/archive/2026/ -
Если редирект сработал — вы окажетесь на главной странице или на странице фильма (в зависимости от примера).
-
Попробуйте изменить год и посмотреть разницу.
При выполнении редиректа вы не увидите кода 302 прямо в браузере,
но можете открыть Инструменты разработчика (F12 → Network) и увидеть,
что первый запрос получил статус 302, а браузер сделал новый запрос по другому адресу.
- Создайте представление
redirect_to_random, которое случайным образом выбирает фильм из списка и перенаправляет на его страницу. - Добавьте маршрут для этого представления.
- Проверьте работу в браузере.
- Попробуйте переделать код, чтобы вместо
redirect()использоватьreverse().
Когда проект становится крупнее, никогда не используйте “жёсткие” пути
(например, redirect('/films/')).
Используйте redirect('route_name') или reverse('route_name').
Так ваш код будет гибким и не сломается при изменении структуры URL.
- Что такое перенаправление (redirect) и зачем оно нужно?
- Чем отличается временный редирект (
302) от постоянного (301)? - Какая функция в Django используется для перенаправлений?
- Зачем использовать параметр
nameвurls.py? - Чем
redirect()отличается отHttpResponseRedirect? - Что делает функция
reverse()и зачем она нужна? - Как проверить, что редирект сработал, в браузере?
- Что произойдёт, если изменить URL в
urls.py, но использовать редирект по имени маршрута? - Как можно использовать
reverse()совместно сredirect()? - Почему важно избегать “жёстких” ссылок в Django?