Flask декораторы before_request и after_request

Flask декораторы before_request и after_request

Автор: Рамис | Статьи 19 января 2023

В этой короткой статье мы рассмотрим способы запуска функций до и после запроса во Flask, используя декораторы before_request и after_request и не только.

Мы начнем с очень простого приложения Flask:

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    print("index is running!")
    return "Hello world"

if __name__ == "__main__":
    app.run()

before_request

Декоратор before_request позволит нам создать функцию, которая будет выполняться перед каждым запросом.

@app.before_request
def before_request_func():
    print("before_request is running!")

Добавив эту функцию в наше приложение и сделав запрос к главной странице сайта/, мы получим в терминале следующий вывод:

before_request is running!
index is running!

before_request идеально подходят для таких задач, как:

  • Открытие соединений с базой данных
  • Загрузка пользователя из сессии
  • Работа с глобальным flask.g объектом

Функция обернутая с помощью @app.before_request, не обязана что-либо возвращать. Если она не возвращает None значение, она будет обработана как функция представления, и любая дальнейшая обработка запросов будет остановлена.

Например:

@app.before_request
def before_request_func():
    print("before_request is running!")
    return "Hello Ramziv.com"

Если вы сделаете какой либо запрос по любому маршруту в своем приложении, вы увидите Hello Ramziv.com, а не Hello world как в нашем примере.

flask before_request

before_first_request

Функции обернутая с помощью @app.before_first_request будут запускаться один раз перед первым запросом к этому экземпляру приложения.

@app.before_first_request
def before_first_request_func():
    print("This function will run once")

Запустив приложение и сделав пару запросов, мы видим следующий вывод:

This function will run once
index is running!
127.0.0.1 - - [06/Jan/2023 18:24:36] "GET / HTTP/1.1" 200 -
index is running!
127.0.0.1 - - [06/Jan/2023 18:24:39] "GET / HTTP/1.1" 200 -

Как вы заметили, функция before_first_request_func запускалась только один раз перед самым первым запросом к приложению и игнорируется при последующих запросах.

after_request

Функция обернутая с помощью декоратора after_request работают так же, как и before_request, за исключением того, что она запустится после каждого запроса.

Важно отметить, что любые функции after_request должны принимать и возвращать объект ответа.

Вот простой пример:

@app.after_request
def after_request_func(response):
    print("after_request is running!")
    return response

Запустив наше приложение и сделав запрос к нашему маршруту /, мы увидим:

before_request is running!
index is running!
after_request is running!

Можете подумать, это отличное место, чтобы сделать что-то вроде закрытие соединение с базой данных. Однако следует отметить, что любые функции обернутые с помощью after_request, НЕ будут работать если ваше приложение вызовет исключение. К счастью, мы можем обойти это с помощью teardown_request.

teardown_request

Функции обернутая с помощью teardown_request ведет себя аналогично after_request функции, однако у нее есть дополнительное преимущество заключающееся в том, что они запускаются независимо от каких-либо исключений.

Это делает функцию с teardown_request отличным местом для выполнения любых операций по очистке после запросов, поскольку мы знаем, что эти функции отработают всегда.

@app.teardown_request
def teardown_request_func(error=None):
    print("teardown_request is running!")
    if error:
        print(error)

Все вместе

Собрав все вместе, наше приложение выглядит так:

from flask import Flask

app = Flask(__name__)

@app.before_first_request
def before_first_request_func():
    print("This function will run once")

@app.before_request
def before_request_func():
    print("before_request is running!")

@app.route("/")
def index():
    print("index is running!")
    return "Hello world"

@app.after_request
def after_request_func(response):
    print("after_request is running!")
    return response

@app.teardown_request
def teardown_request_func(error=None):
    print("teardown_request is running!")
    if error:
        print(error)


if __name__ == "__main__":
    app.run()

Результат

This function will run once
before_request is running!
index is running!
after_request is running!
teardown_request is running!

Заключение

Я привел здесь только несколько примеров, другие полезные функции для работы с запросами как before_request и after_request вы можете найдете в документации Flask.

Комментарии

Markdown
Войти