flask延迟请求回调

在flask官方文档中有这样一段:

延迟请求回调

Flask的一个设计模式是响应对象被创建并在一系列的潜在回调函数中传递,并且可以被修改或者替换。当开始处理请求的时候,可能响应函数还不存在。响应对象可能被一个视图函数或者系统中的其它组成部份创建。

所以如果想修改响应对象但是响应对象还没有创建怎么办?

方法一:把修改响应对象的部分在after-request回调函数中事件 -- 不好

方法二:把修改响应对象的部分绑定在g中,在after-request中再运行

from flask import g

# 将回调函数绑定在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

# 在处理请求之后会被调用,在其中执行修改响应对象的函数
@app.after_request
def call_after_request_callbacks(response):
    for callback in getattr(g, 'after_request_callbacks', ()):
        callback(response)
    return response
    

不是很明白,方法一较于方法二为什么会不好?

阅读 3.9k
1 个回答

首先你可以点击这里查看官方文档的介绍。

如果你直接把你的函数绑定在app.after_request上,那么每次请求之后这个函数都会被调用,你不能阻止这个函数的调用。

如果你一个函数绑定在g上,那么因为g的生命周期与request是相同的,因此你的函数只和当前的request有关。假如你在代码里加入一些判断,例如只有满足一定的条件后,才会把函数绑定到g上,那么其他的不满足条件的request就不会执行这个函数。

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这个函数如果调用,则会把f绑定到g中。

@app.after_request
def call_after_request_callbacks(response):
    for callback in getattr(g, 'after_request_callbacks', ()):
        callback(response)
    return response

上面这段代码的意思是,在每次请求后都判断一下g对象中是否有用户绑定的函数存在,如果有就依次调用。

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

上面这个例子很好地阐述了在没有response对象的时候进行修改。可以看出,当languageNone的时候,remember_language函数是没有被绑定在g对象上的,所以只有language不是None的请求才会执行response.set_cookie函数。

如果你把remember_language直接绑定在app.after_request上,那么每次请求后这个函数都会被执行如:

@app.after_request
def remember_language(response):
    language=something
    response.set_cookie('user_lang', language)

设计函数的一个比较好的原则,就是一个函数只做一件事。如果是这样的话,这个remember_language函数就会变得复杂,因为你还要访问request对象来得到language

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题