Spec-Zone.ru › Flask 0.12

Отложенные обратные вызовы запроса

Одним из принципов проектирования 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/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API