一、问题场景
Flask从客户端接受到请求时,视图函数需要能够接受一些特殊对象,这样才能够处理请求。请求对象 request 就是一个很好的例子,它封装了客户端发送的HTTP请求。
要想让视图函数能够访问请求对象,一种直截了当的方式是将其作为参数传入视图函数,不过这会导致应用中的每个视图函数都多出一个参数。除了访问请求对象,如果视图函数在请求处理时还需要访问其它对象,情况会变得更加糟糕。根据面向对象的思想,显然这样的框架设计是不合理的。
二、解决方案
为了避免大量必须的参数的添加,使得接口繁琐、混乱,Flask使用上下文来统一管理这些特殊的对象,使得这些对象变得全局可以访问。有了上下文之后,就可以像下面这样编写视图函数:
from flask import request
@app.route('/')
def index():
user_agent = request.headers.get('User-Agent')
...
在这个视图函数中我们把 request当做全局变量使用。但是实际上,request不可能是全局变量。想象一下,在多线程服务器中,多个线程同时处理不同客户发送的请求时,每个线程获取到的request对象必然不同。Flask使用上下文让特定的变量在一个线程中全局可访问,但不会干扰其它线程。
更确切的说,request属于请求上下文。Flask有两种上下文,应用上下文和请求上下文。具体如下:
变量名 | 上下文 | 说明 |
---|---|---|
current_app | 应用上下文 | 当前应用的应用实例 |
g | 应用上下文 | 处理请求时用作临时存储的对象,每次请求都会重设这个变量 |
request | 请求上下文 | 请求对象,封装了客户端发出的HTTP请求中的内容 |
session | 请求上下文 | 用户回话,值为一个字典,存储请求与服务器之间需要“记住”的值 |
Flask在分派请求之前推送上下文,请求完之后再将其删除。
参考文献:《Flask Web开发(第二版)》