Flask蓝图应用访问全局变量g.my_db出现AttributeError问题求助
解决Flask中
g.my_db的AttributeError问题 嘿,我来帮你搞定这个Flask里的g对象报错问题!先看看你的代码和报错情况:
问题重现
你的代码结构如下:
main.py:
from flask import Flask, g app = Flask(__name__) with app.app_context(): g.my_db = PostgreSQL() app.register_blueprint(my_app, url_prefix="/my_app")
my_app.py:
from flask import Blueprint, g my_app = Blueprint("my_app", __name__) @my_app.route("/") def index(): return g.my_db.fetch_all() # <<<< ERROR: AttributeError: '_AppCtxGlobals' object has no attribute 'my_db'
问题根源
你现在的写法犯了一个典型的Flask上下文误区:with app.app_context()只是创建了一个临时的一次性应用上下文,这个上下文只在with代码块内部有效,代码块执行完之后,这个上下文就被销毁了。
当用户发起请求时,Flask会自动创建一个全新的请求/应用上下文,这个新上下文里的g对象是干净的,根本没有你之前赋值的my_db属性,所以自然会报错。
解决方案
这里给你几种靠谱的解决方式,按推荐程度排序:
方法1:全局before_request钩子(最推荐)
用Flask的before_request钩子,它会在每个请求处理之前自动执行,确保每次请求的上下文里g都能正确初始化数据库连接:
修改main.py:
from flask import Flask, g app = Flask(__name__) # 每个请求前初始化数据库连接到g对象 @app.before_request def init_db(): g.my_db = PostgreSQL() # 可选:请求结束后关闭数据库连接 @app.teardown_request def close_db(exception): db = g.pop('my_db', None) if db is not None: db.close() # 根据你的PostgreSQL类实现调整关闭逻辑 app.register_blueprint(my_app, url_prefix="/my_app")
方法2:蓝图专属钩子
如果这个数据库连接只在my_app这个蓝图里用到,也可以给蓝图单独注册before_request钩子,这样不会影响其他蓝图的请求:
修改my_app.py:
from flask import Blueprint, g my_app = Blueprint("my_app", __name__) # 仅当前蓝图的请求前初始化数据库 @my_app.before_request def init_db(): g.my_db = PostgreSQL() @my_app.route("/") def index(): return g.my_db.fetch_all()
方法3:手动在视图内处理(不推荐)
如果你非要手动控制上下文,也可以在视图函数里临时创建上下文,但这种写法不够优雅,重复代码多,不建议用于生产环境:
# 注意:需要在my_app.py里导入app对象 from flask import Blueprint, g from main import app my_app = Blueprint("my_app", __name__) @my_app.route("/") def index(): with app.app_context(): g.my_db = PostgreSQL() return g.my_db.fetch_all()
总结
核心就是别用临时的with app.app_context()来初始化请求要用的g属性,用before_request钩子才是符合Flask设计理念的正确姿势,它能保证每个请求的上下文都有你需要的数据库连接。
内容的提问来源于stack exchange,提问作者mortymacs
相关产品推荐
相关产品推荐

