Объект request: данные запроса полностью
request — это объект, в котором Flask собрал всё про входящий запрос: метод, URL-параметры, тело, заголовки, файлы, куки. Один объект — весь запрос.
request доступен внутри любой view-функции как «глобальный» объект, но это контекстная переменная: для каждого запроса Flask подставляет свой экземпляр. Снаружи запроса обращение к request — ошибка.
В прошлом уроке мы читали request.form. На деле в request лежит гораздо больше. Это единая точка доступа ко всему, что прислал клиент. Разберём ключевые атрибуты — они покрывают 95% задач.
| Атрибут | Что содержит |
|---|---|
| request.method | метод: GET, POST, ... |
| request.args | параметры строки запроса (?q=flask) |
| request.form | поля HTML-формы (POST) |
| request.json | тело как JSON (для API) |
| request.files | загруженные файлы |
| request.headers | HTTP-заголовки |
| request.cookies | куки клиента |
from flask import request
@app.route("/search")
def search():
q = request.args.get("q", "")
page = request.args.get("page", 1, type=int)
return f"Ищем '{q}', страница {page}"
Обрати внимание на type=int в .get() — Flask сам приведёт строку из URL к числу, а при ошибке вернёт дефолт. Для API читают request.get_json(), для загрузок — request.files["avatar"].
Контекст запроса — одна из тех концепций, что отличает «копипастера» от понимающего разработчика. Знание, что request — это прокси на верхушку стека, объясняет сразу множество ошибок: почему request недоступен в фоновом потоке, почему его нельзя сохранять между запросами, почему в тестах нужен test_request_context. Тот же механизм лежит под объектами session и g, и под объектом current_app. Раз поняв идею контекста, ты перестаёшь воспринимать эти «глобальные» объекты как магию и начинаешь правильно их использовать. И ещё принцип безопасности: всё, что приходит в request, — это вход от пользователя, потенциально враждебный; валидируй и приводи типы, никогда не доверяй структуре входных данных вслепую.
Как работает под капотом
request — это «контекстно-локальный» объект (proxy). Откуда он знает, какой именно запрос обслуживать, если он один на весь модуль? Flask на входе каждого запроса кладёт реальный объект в стек контекста запроса, а request — лишь указатель на верхушку стека. Поэтому в каждом обработчике request свой, а вне запроса стек пуст и обращение падает.
Запрос A приходит ─▶ push(RequestA) в стек контекста
view читает request ──▶ верхушка стека = RequestA
Запрос A завершён ─▶ pop()
Запрос B приходит ─▶ push(RequestB)
view читает request ──▶ теперь это RequestB
Смоделируем такой контекстный стек обычным Python, чтобы понять, почему «глобальный» request на самом деле разный для каждого запроса.
_stack = []
class RequestProxy:
def __getattr__(self, name):
if not _stack:
raise RuntimeError("Working outside of request context")
return getattr(_stack[-1], name)
class Req:
def __init__(self, path): self.path = path
request = RequestProxy()
def handle(path):
_stack.append(Req(path)) # push контекста
try:
print("view видит путь:", request.path)
finally:
_stack.pop() # pop после ответа
handle("/a")
handle("/b")
try:
request.path # вне запроса
except RuntimeError as e:
print("вне контекста:", e)
Запусти: один и тот же request внутри разных запросов указывает на разные объекты, а снаружи кидает ошибку. Это и есть «магия» контекста запроса в Flask.
Частые ошибки
- Обращаться к request вне запроса. Например в фоновом потоке — «working outside of request context».
- Путать args и form. args — из URL (?...), form — из тела POST.
- Доверять request.json без проверки. Если тело не JSON, get_json вернёт None — проверяй.
Best practices
- Читай значения с дефолтом и type=, не предполагай формат входа.
- Для API используй get_json(silent=True) и валидируй структуру.
- Никогда не доверяй данным из request — это вход от пользователя, валидируй всё.
Что запомнить
- request — единый объект со всеми данными входящего запроса.
- Ключевые атрибуты: method, args, form, json, files, headers, cookies.
- request — контекстно-локальный прокси: для каждого запроса свой экземпляр.
- Вне контекста запроса обращение к request вызывает ошибку.
Итог: request — единый объект со всеми данными запроса, а его «глобальность» обеспечена контекстным стеком: для каждого запроса свой экземпляр. Дальше — как формировать ответы и редиректы.