Flask Web程序工作流程
参考资料:《Flask Web开发实战:入门、进阶与原理解析》作者:李辉
当用户访问一个URL,浏览器便生成对应的HTTP请求,经由互联网发送到对应的Web服务器。Web服务器接收请求,通过WSGI将HTTP格式的请求数据转换成我们的Flask程序能够使用的Python数据。在程序中,Flask根据请求的URL执行对应的视图函数,获取返回值生成响应。
响应依次经过WSGI转换生成HTTP响应,再经由Web服务器传递,最终被发出请求的客户端接收。浏览器渲染响应中包含的HTML和CSS代码,并执行JavaScript代码,最终把解析后的页面呈现在用户浏览器的窗口中。
Flask上下文
编程中的上下文理解为当前环境(environment)的快照(snapshot)。
from flask import request
@app.route('/')
def index():
user_agent = request.headers.get('User-Agent')
return '<p>Your browser is {}</p>'.format(user_agent)
每一个视图函数都需要上下文信息,上例中Flask将请求报文封装在request对象中。按照一般的思路,如果我们要在视图函数中使用它,就得把它作为参数传入视图函数,就像我们接收URL变量一样。但是这样一来就会导致大量的重复,而且增加了视图函数的复杂度。
在前面的示例中,我们并没有传递这个参数,而是直接从Flask导入一个全局的request对象,然后在视图函数里直接调用request的属性获取数据。你一定好奇,我们在全局导入时request只是一个普通的Python对象,为什么在处理请求时,视图函数里的request就会自动包含对应请求的数据?这是因为Flask会在每个请求产生后自动激活当前请求的上下文,激活请求上下文后,request被临时设为全局可访问。而当每个请求结束后,Flask就销毁对应的请求上下文。
我们在前面说request是全局对象,但这里的“全局”并不是实际意义上的全局。我们可以把这些变量理解为动态的全局变量。在多线程服务器中,在同一时间可能会有多个请求在处理。假设有三个客户端同时向服务器发送请求,这时每个请求都有各自不同的请求报文,所以请求对象也必然是不同的。因此,请求对象只在各自的线程内是全局的。Flask通过本地线程(thread local)技术将请求对象在特定的线程和请求中全局可访问。
Flask 中有两种上下文:应用上下文和请求上下文,为了方便获取这两种上下文环境中存储的信息,Flask提供了四个上下文全局变量。
变量名 | 类别 | 说明 |
---|---|---|
current_app | 程序上下文 | 指向处理请求的当前程序实例 |
g | 程序上下文 | 用于存储全局数据,每次请求都会重设 |
request | 请求上下文 | 封装客户端的请求报文数据 |
session | 请求上下文 | 记录请求之间的数据,通过签名的cookie实现 |
如果我们在没有激活相关上下文时使用这些变量,Flask就会抛出
RuntimeError异常:"RuntimeError:Working outside of application
context.“或是"RuntimeErr