Отложенные обратные вызовы запроса
Одним из принципов проектирования Flask является то, что объекты ответа создаются и передаются по цепочке потенциальных обратных вызовов, которые могут их модифицировать или заменить. Когда обработка запроса начинается, объекта ответа еще нет. Он создаётся по мере необходимости либо функцией представления, либо каким-либо другим компонентом системы.
Но что произойдёт, если вы хотите изменить ответ в момент, когда ответа ещё нет? Типичный пример — функция до запроса, которая хочет установить cookie в объекте ответа.
Один из способов — избежать этой ситуации. Очень часто это возможно. Например, вы можете попытаться перенести эту логику в обратный вызов после запроса. Иногда, однако, перемещение этого кода туда не очень удобно или делает код очень громоздким.
В качестве альтернативы вы можете прикрепить множество функций обратного вызова к объекту g и вызвать их в конце запроса. Таким образом, вы можете отложить выполнение кода из любой точки приложения.
Декоратор
Следующий декоратор является ключевым. Он регистрирует функцию в списке в объекте g:
from flask import g
def after_this_request(f):
if not hasattr(g, 'after_request_callbacks'):
g.after_request_callbacks = []
g.after_request_callbacks.append(f)
return f
Вызов отложенного
Теперь вы можете использовать декоратор after_this_request для обозначения функции, которая должна быть вызвана в конце запроса. Но нам всё ещё нужно их вызвать. Для этого следующая функция должна быть зарегистрирована как обратный вызов after_request():
@app.after_request
def call_after_request_callbacks(response):
for callback in getattr(g, 'after_request_callbacks', ()):
callback(response)
return response
Практический пример
В любое время во время запроса мы можем зарегистрировать функцию, которая будет вызвана в конце запроса. Например, вы можете запомнить текущий язык пользователя в cookie в функции до запроса:
from flask import request
@app.before_request
def detect_user_language():
language = request.cookies.get('user_lang')
if language is None:
language = guess_language_from_request()
@after_this_request
def remember_language(response):
response.set_cookie('user_lang', language)
g.language = language
© 2007–2020 Pallets
Licensed under the BSD 3-clause License.
https://flask.palletsprojects.com/en/0.12.x/patterns/deferredcallbacks/