Flask蓝图如何以代理模式访问自定义SQLAlchemy数据库会话
错误根因
你在walletapp.py模块顶层直接访问current_app.config获取配置,模块导入阶段还没有初始化Flask应用、也没有推送应用上下文,因此直接触发上下文不存在的报错。
解决方案
方案1:视图内取值(最简实现)
把db、abort、app的取值逻辑移到视图函数内部,请求触发视图执行时Flask会自动推送应用上下文,此时访问current_app是合法的。
修改后walletapp.py代码:
from flask import Blueprint, current_app main = Blueprint('main', __name__) # Get wallet list @main.route('/v1/wallets', methods=['GET']) def get_wallets(): ''' Get all the wallets and their balances ''' db = current_app.config['database'] abort = current_app.config['abortion'] app = current_app wallets = db.query(models.Wallet).all() result = wallets_schema.dump(wallets) resp = cook_response(app, {'wallets': result}) return resp, 200
方案2:LocalProxy代理(仿current_app逻辑)
如果不想每个视图都重复写取值逻辑,可以用Werkzeug的LocalProxy封装代理对象,只有实际调用对象属性时才会从上下文取值,导入阶段不会触发实际的访问逻辑,完美匹配你要的代理模式效果。
修改后walletapp.py代码:
from flask import Blueprint, current_app from werkzeug.local import LocalProxy main = Blueprint('main', __name__) # 定义代理对象,仅实际调用时才从上下文取配置 db = LocalProxy(lambda: current_app.config['database']) abort = LocalProxy(lambda: current_app.config['abortion']) app = LocalProxy(lambda: current_app) # Get wallet list @main.route('/v1/wallets', methods=['GET']) def get_wallets(): ''' Get all the wallets and their balances ''' wallets = db.query(models.Wallet).all() result = wallets_schema.dump(wallets) resp = cook_response(app, {'wallets': result}) return resp, 200
额外注意项
你的wsgi.py中with app.app_context:写法有误,需要加括号修正为with app.app_context():,否则上下文不会正确推送,后续操作可能仍有上下文错误。
两种方案都完全保留了蓝图的插拔性,单元测试时只需给测试实例的config传入模拟的数据库对象即可,无需修改蓝图内部代码。
内容的提问来源于stack exchange,提问作者dexpiper
相关产品推荐
相关产品推荐

