Каждая HTTP-сессия определяется двумя вещами — запросом и ответом. Запрос формируется клиентом, например браузером, а ответ — сервером. В этом уроке разберем объекты request
и response
, которые извлекают данные запроса и формируют ответ. Также покажем способы, с помощью которых из объекта request
извлекаются параметры.
Request и response
И запрос и ответ во Flask представлены двумя объектами - request
и response
, обратиться к которым можно внутри каждого обработчика маршрута:
from flask import request
@app.route("/")
def hello_world():
return "Hello, World!"
Глобальный объект request
используется, чтобы извлекать данные запроса, например, заголовков или содержимого отправленной формы. request
- неизменяемый объект. Запрос уже выполнили со стороны клиента, и он не может поменяться:
from flask import request
@app.route("/")
def hello_world():
print(request.headers) # Выводит все заголовки
return "Hello, World!"
curl locahost:5000/
Hello, World!
# в терминале запущенного приложения
Host: localhost:5000
User-Agent: curl/7.81.0
Accept: */*
127.0.0.1 - - "GET / HTTP/1.1" 200 -
Для ответа же используется объект response
. По умолчанию Flask самостоятельно формирует объект response
и его не нужно передавать явно. Flask сам определяет формат возвращаемого контента из обработчика и подставляет нужный формат данных в заголовке:
from flask import render_template
@app.route("/json/")
def json():
return {"json": 42} # Возвращает тип application/json
@app.route("/html/")
def html():
return "<h1>Hello, world!</h1>" # Возвращает тип text/html
Если вернуть вместе с телом в виде кортежа-пары еще и число, то клиент получит соответствующий код ответа:
@app.route("/not_found")
def not_found():
return "Oops!", 404
curl -IS localhost:5000/not_found
HTTP/1.1 404 NOT FOUND
Server: Werkzeug/3.0.6 Python/3.13.0rc2
Content-Type: text/html; charset=utf-8
Content-Length: 5
Connection: close
Разумеется мы не можем перечислить все несуществующие пути, чтобы отдавать по ним коды ошибок. Потому для обработки типичных ошибок вроде «Страница не найдена» во Flask есть особый синтаксис обработчика ошибок. На первый взгляд, обработчик ошибок выглядит как обработчик запросов. Только разница в том, что обработчики ошибок получают в качестве аргумента объект ошибки error
. Вот так можно было бы оформить «Страницу 404»:
# вместо пути указываем код ошибки
@app.errorhandler(404)
def not_found(error):
return "Oops!", 404
В большинстве случаев нам достаточно тела ответа и статуса и не нужно явно использовать объект response
- Flask самостоятельно оборачивает в него возвращаемые данные. Но если нам надо большее, то нужно использовать функцию make_response()
. Она принимает тело ответа и возвращает объект ответа - flask.Response
. Объект ответа можно модифицировать разными способами и затем вернуть из обработчика:
from flask import make_response
@app.route("/hello")
def hello():
# создаем объект response
response = make_response("Hello, World!")
# Устанавливаем заголовок
response.headers["X-MyHeader"] = "Thats my header!"
# Меняем тип ответа
response.mimetype = "text/plain"
# Задаем статус
response.status_code = 201
# Устанавливаем cookie
response.set_cookie("super-cookie", "42")
return response
В примере выше мы создали объект ответа с телом 'Hello, World!'
, затем установили в нем наш заголовок, изменили тип ответа, задали куку и статус ответа. Наконец, собранный ответ вернули из обработчика.
curl -i localhost:5000/hello
HTTP/1.1 201 CREATED
Server: Werkzeug/3.0.6 Python/3.13.0rc2
Content-Type: text/plain; charset=utf-8
Content-Length: 13
X-MyHeader: Thats my header!
Set-Cookie: super-cookie=42; Path=/
Connection: close
Hello, World!%
Параметры запроса
Параметры запроса, или еще их называют query string
— это не часть маршрута и они не влияют на выбор обработчика. Связано это с тем, что такие параметры используются для различных вспомогательных целей. Например, параметр page
, обозначает страницу просматриваемого списка. Обработчик в такой ситуации всегда один и тот же, а данные показываются разные:
curl 'localhost:8000/users?page=4&per=3'
GET /users
Параметры извлекаются из объекта запроса. По атрибуту request.args
возвращается объект, который похож на словарь, несколькими способами:
request.args
– извлекает все параметрыrequest.args.get(name, default=None, type=None)
– извлекает значение конкретного параметра в формате строки. Если параметр не найден, приложение продолжает работу, а метод вернетdefault
. С помощьюtype
можно привести параметр к определенному типу. Если привести к указанному типу невозможно, возникнет исключениеValueError
# равноценно запросу GET localhost/users?page=12&per=5 в браузере
curl -G -d page=12 -d per=5 localhost/users
@app.route("/users/")
def get_users():
print(request.args) # => {'page': 12, 'per': 5}
page = request.args.get("page", 1)
per = request.args.get("per", 10, type=int)
# Обработка
prev_page = (page - 1) * per
current_page = page * per
users_at_page = users[prev_page:current_page]
return users_at_page
Количество обработчиков и маршрутов, которые можно добавить, ничем не ограничено. При этом микрофреймворки не задают никакой структуры. Если кода становится много, то разделять его по файлам придется самостоятельно.
Самостоятельная работа
- Измените в example.py следующий обработчик:
@app.post('/users')
def users():
return 'Users', 302
- Выполните POST-запрос на него с помощью curl. Убедитесь, что произошел редирект:
# Подставьте ваши параметры
# --head – покажет заголовки
# -X POST – отправит POST запрос
curl --head -X POST localhost:8000/users
Эталонное приложение
Дополнительные материалы
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.