狗书第 2 章笔记

2.5.1 程序和请求上下文

Flask 从客户端收到请求时,要让视图函数能访问一些对象,这样才能处理请求。请求对象就是一个很好的例子,它封装了客户端发送的 HTTP 请求。
要想让视图函数能够访问请求对象,一个显然的方式是将其作为参数传入视图函数,不过这会导致程序中的每个视图函数都增加一个参数。除了访问请求对象,如果视图函数在处理请求时还要访问其他对象,情况会变得更糟。为了避免大量可有可无的参数把视图函数弄得一团糟,Flask 使用上下文临时把某些对象变为全局可访问。有了上下文,就可以写出下面的视图函数:

from flask import request

@app.route('/')
def index():
    user_agent = request.headers.get('User-Agent') 
    return '<p>Your browser is {}</p>'.format(user_agent)

注意在这个视图函数中我们如何把 request 当作全局变量使用。事实上,request 不可能是全局变量。试想,在多线程服务器中,多个线程同时处理不同客户端发送的不同请求时, 每个线程看到的 request 对象必然不同。Falsk 使用上下文让特定的变量在一个线程中全局可访问,与此同时却不会干扰其它线程。

线程是可单独管理的最小指令集。进程经常使用多个活动线程,有时还会共享内存或文件句柄等资源。多线程 Web 服务器会创建一个线程池,再从线程池中选择一个线程用于处理接收到的请求。

在 Flask 中有两种上下文:程序上下文和请求上下文。
下表列出了这两种上下文提供的变量:

变量名 上下文 说明
current_app 程序上下文 当前激活的程序实例
g 程序上下文 处理请求时,用作临时存储的变量,每次请求都会重置此变量
request 请求上下文 请求对象,封装了客户端发出的 HTTP 请求中的内容
session 请求上下文 用户会话,用于存储请求之间需要记住的值的字典

Flask 在分发请求之前激活程序 / 请求上下文,请求处理完成后再将其删除。程序上下文被推送后,就可以在线程中使用 current_app 和 g 变量。类似地,请求上下文被推送后,就可以使用 request 和 session 变量。如果使用这些变量时我们没有激活程序上下文或请求上下文,就会导致错误。
下面的代码演示导入程序上下文并使用 current_app 的方法:

In [6]: from hello import app

In [7]: from flask import current_app

In [8]: app.app_context().push()

In [9]: current_app.name
Out[9]: 'hello'

2.5.3 请求钩子

请求钩子在处理请求之前或之后执行,有时会很有用。例如在请求开始时,我们可能需要创建数据库连接或者认证发起请求的用户。为了避免在每个视图函数中都使用重复的代码,Flask 提供了注册通用函数的功能,注册的函数可在请求被分发到视图函数之前或之后调用。
请求钩子使用装饰器实现,Flask 支持以下四种,注册一个函数:
before_first_request:在处理第一个请求之前运行。
before_request:在每次请求之前运行。
after_request:如果没有未处理的异常抛出,在每次请求之后运行。
teardown_request:即使有未处理的异常抛出,也在每次请求之后运行。

猜你喜欢

转载自blog.csdn.net/weixin_34111819/article/details/86839173