延迟请求回调

Flask 的设计原则中有一条是响应对象被创建并在一条可能的回调链中传递,而在 这条回调链但中的任意一个回调,您都可以修改或者替换掉他们。 当请求开始被 处理时,还没有响应对象,响应对象将在这一过程中,被某个视图函数或者系统 的其他组件按照实际需要来闯将。 它根据需要通过视图函数或系统中的一些其他组件创建。

但是,如果您想在响应过程的结尾修改响应对象,但是这是对象还不存在,那么会发生 什么呢? 一个常见的例子是您可能需要在 before-request 函数当中在响应对象上 设定 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

调用Deferred

现在您可以使用 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

A实例

然后在 请求结束的时候调用他们。 例如,您可以在before-request函数中的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