flask核心机制
flask的经典错误:working outside application context,不在上下文环境中
flask提供两种上下文:应用上下文(AppContext)和请求上下文(RequestContext)
应用上下文提供对核心对象Flask的封装,请求上下文是对请求对象Request的封装
AppContext把实例化的app作为属性存放
这个AppContext对象下面定义了四个方法:push、pop、enter、exit
RequestContext同样定义相同的四个方法,这四个方法和栈结构是紧密相关的
Flask核心对象存储在Appcontext对象中,而Request请求对象存储在RequestContext中
外部的一些参数或者数据和flask核心对象Flask一起组成新的对象就是上下文,同时在上下文上面提供一系列方法
Flask核心对象里面承载各种功能,如配置文件信息,提供注册路由或者视图函数功能
Request请求对象保存了请求信息,相关URL的参数等
操作这两个对象不是from引入使用,而是从context间接拿到对象,context也不是引入使用
current_app和request的localProxy提供了间接操纵上下文的能力
代理模式的实现涉及到flask的一系列机制,如下图
当一个请求进入flask中之后,flask首先会实例化一个RequestContext请求上下文,它封装了此次请求的相关信息,在Request中,当实例化请求上下文后会把它推入栈中
栈:后进先出 队列:先进先出
flask用LocalStack来表示一个栈,将LocalStack实例化存储在_request_ctx_stack中,或者_app_ctx_stack中
入栈就是用四个方法中的push方法实现的,RequestContext入栈之前会先检查_app_ctx_stack栈顶元素是否为空,如果空,会先推入一个AppContext对象进栈,然后推入RequestContext
当操作current_app(LocalProxy)和request(LocalProxy)这两个代理时相当于间接操作两个栈顶的元素,也就是两个上下文,当两个栈顶元素不为空,就不会出现working outside application context这种错误
想要避免这种错误就需要把上下文推入栈中,首先要先得到应用上下文对象,flask核心对象提供一个方法app.app_context得到flask的AppContext
from flask import Flask, current_app app = Flask(__name__) ctx = app.app_context() ctx.push() a = current_app b = current_app.config['DEBUG'] ctx.pop()
最终current_app返回了flask的核心对象,而不是应用上下问
current_app: "Flask" = LocalProxy(_find_app) def _find_app(): top = _app_ctx_stack.top if top is None: raise RuntimeError(_app_ctx_err_msg) return top.app
还有一种简便的方法就是使用with
with app.app_context(): a = current_app() b = current_app.config['DEBUG']