Зарегистрируйтесь, чтобы продолжить обучение

Обработчики запросов Python: Веб-разработка (Flask)

Одна из содержательных частей цикла запрос-ответ — обработчик запроса. В этом уроке мы разберем, как находить и вызывать обработчика.

Обработчик

Общий принцип работы любого веб-фреймворка отражает архитектуру HTTP. На каждый адрес задается обработчик (handler) — функция, которая выполняет необходимые действия и возвращает ответ.

Обработчики регистрируются с помощью декоратора @route(). Декоратор принимает путь или маршрут, для которого вызовется обработчик:

@app.route('/')
def index():
    # …

@app.route('/data/users/')
def users():
    # …

Каждый путь состоит из сегментов — строк, которые разделены слешами ("/"). Функции index и users в примере — обработчики, а каждое применение декоратора route — добавление нового правила маршрутизации.

Во фреймворках принято определять маршрут как комбинацию метода HTTP и адреса. И это соответствует идеям REST. Flask предлагает два способа указания метода:

  • Как аргумент декоратора route() — все указанные методы будут обрабатываться одной функцией, а выбор метода будет в условиях:
from flask import request


@app.route("/", methods=["GET", "POST"])
def hello():
    # Получить доступ к содержимому запроса можно через специальный объект request
    if request.method == "POST":
        return "Hello, POST!"
    return "Hello, GET!"
  • Как отдельные обработчики под каждый метод с помощью соответствующих декораторов: get(), post() и других:
@app.get("/")
def hello_get():
    return "Hello, GET!"


@app.post("/")
def hello_post():
    return "Hello, POST!"

Теперь с помощью утилиты curl мы можем выполнить запросы к нашему приложению и проверить, какие сообщения выводятся при GET и POST-запросах:

curl -X GET localhost:8000

# Hello, GET!

curl -X POST localhost:8000

# Hello, POST!

Диспетчеризация

Процесс поиска нужного обработчика называется диспетчеризацией. Она выполняется в два этапа: до входа во фреймворк и после входа в приложение. Разберем шаги каждого этапа.

До входа в фреймворк:

  1. Клиент выполняет запрос к веб-серверу, который расположен на сервере. Клиент — это не обязательно браузер, в примере клиент — это программа curl
  2. Веб-сервер перенаправляет запрос приложению и устанавливает правильные параметры запроса

После входа в приложение — происходит диспетчеризация:

  1. Фреймворк анализирует параметры запроса и пытается сопоставить маршруты, которые добавлены в объект app с тем, что пришло. Он сравнивает комбинацию адреса и метода. Если метод не указан в правиле, то по умолчанию предполагается GET. Этот процесс называется роутингом или маршрутизацией. А место, где внутри хранятся все добавленные маршруты, называют роутером
  2. Если в процессе роутинга нашелся соответствующий маршрут, то вызывается его обработчик
  3. Ответ, который сформировал обработчик, отправляется обратно клиенту

Рассмотрим конкретный пример:

from flask import Flask, request

app = Flask(__name__)


@app.route("/")
def index():
    return "Hello, World!"


@app.route("/users/", methods=["GET", "POST"])
def users():
    if request.method == "POST":
        return "Hello from POST /users/"
    return "Hello from GET /users/"

После запуска этого кода формируется роутер, который содержит в себе три маршрута. Посмотреть карту маршрутов можно командой flask routes:

export FLASK_APP=example:app
python -m flask routes

Endpoint  Methods    Rule
--------  ---------  -----------------------
index     GET        /
users     GET, POST  /users/
# Flask по умолчанию также создает маршрут для static файлов, мы его не рассматриваем в этом уроке

Теперь предположим, что клиент выполнил такой запрос:

curl -X POST localhost:8000/users
# Hello from POST /users/

После этого последуют следующие действия:

  1. Веб-сервер вызвал наше приложение app
  2. Фреймворк сопоставил маршрут POST /users и нашел, что за этот запрос отвечает обработчик users()
  3. Фреймворк вызвал обработчик, который вернул клиенту ответ: 'Hello from POST /users'

Фреймворк может не обнаружить соответствия. Например, если клиент запросит страницу /comments. Тогда фреймворк по умолчанию возьмет управление на себя и автоматически отдаст браузеру ответ 404 — страница не найдена:

curl localhost:8000/comments
# <!doctype html>
# <html lang=en>
# <title>404 Not Found</title>
# <h1>Not Found</h1>
# <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>

Всегда внимательно смотрите, какие делаются запросы и есть ли подходящие под них ответы. Так вам не придется задаваться вопросом, почему браузер ничего не показывает. Проще всего увидеть ответ от сервера через консоль разработчика вашего браузера:

DevTool Network

Она есть в каждом браузере. Попробуйте открыть ее и понаблюдать за процессом загрузки.


Самостоятельная работа

Добавьте обработчики в файл example.py, который мы создали в самостоятельной работе предыдущего урока:

@app.get("/users")
def users_get():
    return "GET /users"


@app.post("/users")
def users_post():
    return "POST /users"

Откройте в браузере эту страницу. Убедитесь что на экран вывелся текст, переданный в GET-обработчике. Выполните POST-запрос с помощью curl. Убедитесь, что вывелся текст, переданный в POST-обработчике.

Эталонное приложение

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff