我们使用flask中常看到"上下文"这个概念,实际开发中也较少遇到需要自己去推上下文的场景,但是应用规模扩展较大的时候我们和可能就会遇到需要去推上下文的场景了。
flask的上下文机制实际是通过环境隔离来解决数据访问的问题,flask根据werkzeug.local模块中实现的一种数据结构LocalStack用来存储“请求上下文”对象。
flask中的上下文分为请求上下文和应用上下文
1.应用上下文
在应用启动开始就绑定全局app对象,这样我们就能在整个应用周期内访问存储的数据,通常我们在非请求(视图函数中)需要访问应用配置,数据库实例时就可以直接来获取,应用上下文的生命周期就是整个应用启动一直到应用结束或者关闭。
应用上下文的核心对象如下:
current_app:通过代理机制指向当前活动的应用实例,用于访问应用级配置current_app.config,和扩展,例如数据库对象,缓存对象等等。
g 对象:一个临时存储容器(全局作用域),用于在应用上下文的生命周期内传递数据(如数据库连接、用户身份对象)。
2.请求上下文
请求上下文就是针对于每个请求,它的生命周期也就是从请求访问和请求结束,当flask接受到请求,并通过 LocalStack 推入当前线程的本地栈,使 request 和 session 在当前请求所有的对中都可以使用。
请求上下文的核心对象如下:
request:封装 HTTP 请求的全部信息,包括 URL、方法、参数、表单数据、请求头、上传文件等。
session:用于存储用户会话数据(如登录状态),数据经加密后存储在客户端 Cookie 中。
上面介绍完可能大家还没有看懂,实际在我们开发中,例如我遇到的情况,如果我需要使用peewee去创建数据库和插入数据,这个时候我们会制作一个cli工具,这个工具并非在flask启动应用中引用,实际意思也就是脱离了flask生命周期中的一个独立文件,我需要使用它来创建数据库,这个时候我们就需要进行手动上下文的推入,例如
手工推入请求上下文,使用上下文管理器
with app.test_request_context():
或者手工推入应用上下文,使用上下文管理器
with app.app_context():
实际代码如下
from apps.application import create_app
app = create_app()
#创建数据表,存在就会自动跳过
@app.cli.command("create_tb")
def create_tb():
try:
with app.app_context():
data_proxy.connect()
data_proxy.create_tables([BTag], safe=True)
print("数据表创建成功, 当前数据表: {}".format(data_proxy.get_tables()))
if not data_proxy.is_closed():
data_proxy.close()
except Exception as e:
print("数据表创建失败, {}".format(e))
如果去掉了推入上下文就会报错,因为推入上下文时,数据库才会实际进行初始化,那么上下文生命周期中的所有表对象就均可以使用。
实际在创建请求上下文的同时会自动激活应用上下文,确保应用上下文的一些对象可用,例如current_app对象。无论是请求上下文还是应用上下文,底层均依赖 LocalStack 数据结构 实现线程/协程安全的隔离。
内容版权声明:除非注明,否则皆为本站原创文章。
转载注明出处:https://sulao.cn/post/1046
评论列表