Жизненный цикл запроса и middleware
Чтобы по-настоящему понять Django, нужно проследить жизнь одного запроса от клика в браузере до готовой страницы. Это «скелет», на который нанизывается всё остальное.
Суть: запрос проходит через сервер, middleware и URL-резолвер, попадает в view, которая собирает данные и возвращает HttpResponse; ответ снова идёт через middleware к клиенту.
Полный жизненный цикл запроса
Когда пользователь открывает example.com/blog/42/, происходит длинная, но строго упорядоченная цепочка событий. Понимание этого порядка избавит вас от половины будущих багов — вы будете знать, где именно «ломается» запрос.
1. Браузер шлёт GET /blog/42/
│
2. WSGI/ASGI-сервер принимает соединение
│
3. Middleware (вниз):
SecurityMiddleware → SessionMiddleware
→ AuthenticationMiddleware → CsrfViewMiddleware
│
4. URLconf: /blog/42/ совпал с path("blog/<int:pk>/")
│
5. View вызывается: post_detail(request, pk=42)
│ ┌─────────────┐
├──────────▶│ ORM/Model │ SELECT ... WHERE id=42
│ └─────────────┘
6. View рендерит template с данными
│
7. Возвращается HttpResponse(200, html)
│
8. Middleware (вверх, обратный порядок)
│
9. Сервер отдаёт ответ браузеру
Объект request
В каждую view Django передаёт объект HttpRequest — это «конверт» со всей информацией о запросе. Самые важные его атрибуты: request.method (GET, POST), request.GET и request.POST (данные форм и query-параметры), request.user (текущий пользователь), request.path (путь). Простейшая view выглядит так:
from django.http import HttpResponse
def hello(request):
name = request.GET.get("name", "гость")
return HttpResponse(f"Привет, {name}!")
Откройте /?name=Аня — и в ответ прилетит «Привет, Аня!». Это и есть атом Django: функция, которая берёт request и возвращает response.
Middleware: слои-обёртки
Middleware — это список обработчиков, через которые проходит каждый запрос «вниз», а каждый ответ — «вверх». Они объявлены в settings.py в списке MIDDLEWARE. Именно middleware незаметно подключает куку сессии, определяет request.user и проверяет CSRF-токен у POST-запросов. Порядок в списке важен: каждый слой оборачивает следующий, как матрёшка.
Как это работает под капотом
По сути URL-резолвер — это перебор правил: он идёт по списку маршрутов сверху вниз и берёт первый подходящий шаблон, извлекая из URL именованные части (как pk=42). Это языко-независимая логика, которую легко смоделировать на чистом Python:
# Попробуй сам ▶ — мини-роутер в духе Django URLconf
import re
routes = [
(r"^/$", "home"),
(r"^/blog/$", "post_list"),
(r"^/blog/(\d+)/$", "post_detail"),
(r"^/about/$", "about"),
]
def resolve(path):
for pattern, view in routes:
m = re.match(pattern, path)
if m:
return view, m.groups()
return "404_not_found", ()
for url in ["/", "/blog/", "/blog/42/", "/missing/"]:
view, args = resolve(url)
print(f"{url:14} -> {view} {args}")
Django делает то же самое, только мощнее: разбирает типы (int, slug, uuid), именует группы и кеширует разбор. Но принцип — «первый подошедший шаблон выигрывает» — ровно такой же.
GET против POST
GET-запрос запрашивает данные и не должен менять состояние сервера (открыть страницу, поискать). POST отправляет данные, которые что-то меняют (создать пост, залогиниться). Это не просто соглашение: браузеры кешируют GET, повторяют его при «назад», а POST требует подтверждения. View почти всегда проверяет метод и ветвится по нему.
Частые ошибки
- Менять данные в GET-запросе. Удаление по GET-ссылке выполнят поисковые роботы и префетч браузера.
- Забыть про порядок middleware. Если переставить слои, аутентификация или CSRF могут перестать работать.
- Читать
request.POSTпри GET-запросе. Он будет пустым — всегда проверяйтеrequest.method. - Не возвращать HttpResponse. View обязана что-то вернуть, иначе будет ошибка.
Best practices
- Держите views тонкими: логику выносите в модели и сервисы.
- Используйте
request.GET.get("ключ", default), чтобы не падать на отсутствующем параметре. - Соблюдайте семантику HTTP-методов — это влияет на кеширование и безопасность.
Итоги
Жизненный цикл запроса — сервер, middleware, URLconf, view, ответ. Объект request несёт всё о запросе, HttpResponse — всё об ответе. URL-резолвер выбирает первый подходящий маршрут. Этот скелет лежит в основе всех следующих разделов.