前言
前面几章对flask的一个基本的使用进行了一个入门,那么这一章将会对flask的核心对象以及其运行原理进行讲解。
画张图吧
与其枯燥的干讲,不如画张图吧。
flask中的上下文
关于python中的上下文如果比较陌生的话,可以看我的另一篇文章。链接
在flask中最重要的两个对象,就是请求上下文和应用上下文,先来看看部分源码。
_request_ctx_stack = LocalStack()
_app_ctx_stack = LocalStack()
current_app = LocalProxy(_find_app)
request = LocalProxy(partial(_lookup_req_object, "request"))
session = LocalProxy(partial(_lookup_req_object, "session"))
g = LocalProxy(partial(_lookup_app_object, "g"))
这些源码跟上图是对应的。_request_ctx_stack ,_app_ctx_stack 是两个栈用来存放我们的请求和应用的对象。
请求上下文
当一个请求过来的时候flask会实例化一个 Request 为 Request Context对象推入栈中。但是在推入栈之前,会检查_app_ctx_stack context栈顶是否为空,如果为空或者栈顶元素跟我们当前的 Request Context 不对应的话会实例化一个 Appcontext (应用上下文)入栈。当我们在使用current_app 和 request 对象时,实际上就是操作栈顶的元素。
应用上下文
应用上下文即为flask实例化的appcontext 对象。当有请求访问时会把appcontext 推入栈中,请求结束时则又会弹出栈。非常重要的是我们在代码中使用的 current_app 以及 request 对象其实不是上下文,而是真正的 app 核心对象 或者 Request 对象。
flask中经典问题
Working outside of application context
这个问题,我想使用flask做开发的同学经常能遇到,其实就是找不到
python
app context 对象
from flask import Flask,current_app
app = Flask(__name__)
test_current_app = current_app
test_config = current_app.config['DEBUG']
运行上述代码就会报flask 中的经典错误。
Working outside of application context
这个问题的原因是什么呢,我们刚才说了当有一个请求过来的时候,flask才会把 request context 推入栈中,在此之前也会把 app context 推入栈中。但此时没有请求,所以我们的_app_ctx_stack 的栈顶为空的,自然而然的我们就找不到我们的appcontext对象。
解决办法
知道了问题的原因,解决办法就比较简单了,我们只需手动的推入一个appcontext入栈即可。
with app.app_context():
test_current_app = current_app
test_config = current_app.config['DEBUG']
在代码前加入这两句即可