每一个视图函数都需要上下文信息,Flask将请求报文封装在request对象中。按照一般的思路,如果我们要在视图函数中使用它,就得把它作为参数传入视图函数,就像我们接收URL变量一样。但是这样一来就会导致大量的重复,而且增加了视图函数的复杂度。

在前面的示例中,我们并没有传递这个参数,而是直接从Flask导入一个全局的request对象,然后在视图函数里直接调用request的属性获取数据。我们在全局导入时request只是一个普通的Python对象,为什么在处理请求时,视图函数里的request就会自动包含对应请求的数据?这是因为Flask会在每个请求产生后自动激活当前请求的上下文,激活请求上下文后,request被临时设为全局可访问。而当每个请求结束后,Flask就销毁对应的请求上下文。

我们在前面说request是全局对象,但这里的全局并不是实际意义上的全局。我们可以把这些变量理解为动态的全局变量。

在多线程服务器中,在同一时间可能会有多个请求在处理。假设有 三个客户端同时向服务器发送请求,这时每个请求都有各自不同的请求 报文,所以请求对象也必然是不同的。因此,请求对象只在各自的线程 内是全局的。Flask通过本地线程(thread local)技术将请求对象在特定 的线程和请求中全局可访问。

为了方便获取这两种上下文环境中存储的信息,Flask提供了四个上下文全局变量

提示:

这四个变量都是代理对象(proxy),即指向真实对象的代理。一般情况下,我们不需要太关注其中的区别。在某些特定的情况下,如果你需要获取原始对象,可以对代理对象调用_get_current_object()方法获取被代理的真实对象。

current_app 程序上下文 指向处理请求的当前程序实例

g 程序上下文  替代Python的全局变量用法,确保仅在当前请求中可用。用于存储全局数据,每次请求都会重设

request 请求上下文 封装客户端发出的请求报文数据

session  请求上下文 用于记住请求之间的数据,通过签名Cookie实现

既然有了程序实例app对象,为什么还需要current_app变量。在不同的视图函数中,request对象都表示和视图函数对应的请求,也就是当前请求(current request)。而程序也会有多个程序实例的情况,为了能获取对应的程序实例,而不是固定的某一个程序实例,我们就需要使用current_app变量

因为g存储在程序上下文中,而程序上下文会随着每一个请求的进 入而激活,随着每一个请求的处理完毕而销毁,所以每次请求都会重设 这个值。我们通常会使用它结合请求钩子来保存每个请求处理前所需要 的全局变量,比如当前登入的用户对象,数据库连接等。在前面的示例 中,我们在hello视图中从查询字符串获取name的值,如果每一个视图都 需要这个值,那么就要在每个视图重复这行代码。借助g我们可以将这 个操作移动到before_request处理函数中执行,然后保存到g的任意属性 上

from flask import g
@app.before_request def get_name():
g.name = request.args.get('name')

设置这个函数后,在其他视图中可以直接使用g.name获取对应的 值。另外,g也支持使用类似字典的get()、pop()以及setdefault() 方法进行操作。


0 Comments latest

No comments.