在使用python的Flask框架跟着教程编写项目时,我跟着教程使用了三个文件来组织,分别是main.py(主程序),module.py(数据库模型),controller.py(蓝图模块程序,用Blueprint衔接)
在主程序中,创建app、SQLalchemy实例对象db并将二者绑定
app = Flask(__name__, static_url_path='/') # 配置app参数 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:password@localhost:3306/ayangnote?charset=utf8' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # True跟踪数据库的修改,及时发送信号 # 实例化db对象,绑定flask的app db = SQLalchemy(app)
在module.py中,导入主程序中的db和app,创建子类Users作为查询表,并定义数据库查询的方法
from main import db # 直接引用main模块中的全局变量 class Users(db.Model): __table__ = Table('users', db.metadata, autoload_with=db.engine, mysql_bind=db.engine) def find_user_by_id(self, userid): row = db.session.query(Users).filter(Users.userid == userid).first() return row def find_user_by_id2(self, userid): row = Users.query.filter(Users.userid == userid).first() return row
controller.py与主程序通过Blueprint衔接,并且创建查询接口和指定操作
但我写完后,运行起来报错RuntimeError: Working outside of application context.表示缺少上下文
在查询相关解决方案后,我试图理解了一下Flask框架上下文机制的原理,增加代码with app.app_context():
参考链接:关于flask中 RuntimeError: Working outside of application context 引发的问题(flask中的上下文机制)
module修改1.py
from main import db,app # 直接引用main模块中的全局变量 # 创建上下文 with app.app_context(): class Users(db.Model): __table__ = Table('users', db.metadata, autoload_with=db.engine, mysql_bind=db.engine) def find_user_by_id(self, userid): row = db.session.query(Users).filter(Users.userid == userid).first() return row def find_user_by_id2(self, userid): row = Users.query.filter(Users.userid == userid).first() return row
这样修改完,仍然在页面报错RuntimeError: The current Flask app is not registered with this 'SQLAlchemy' instance. Did you forget to call 'init_app', or did you create multiple 'SQLAlchemy' instances?
我意识到是两个文件中应用的SQLAlchemy对象可能并非同一个(现在仍然不知道为啥,如有人知道求告知!)最终在chatgpt的帮助下得出一个比较笨,但很简单的解决方案:
解决方案如下:
具体来说,SQLAlchemy 对象需要知道它将要与哪个 Flask 应用程序实例绑定。如果在不同的 Python 文件中创建了不同的 Flask 实例,并且在每个文件中都创建了一个 SQLAlchemy 实例,则会导致这个问题。为了解决这个问题,你可以考虑将 SQLAlchemy 实例单独放在一个模块中,然后在需要使用它的地方导入它。同时,在 main.py 中导入其他模块时,也要确保它们使用的是相同的 Flask 实例。
以下是一个可能的解决方案:
- 在一个单独的文件(例如 database.py)中创建一个 SQLAlchemy 实例,代码如下:
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()- 在主程序 main.py 中导入 db 对象并绑定到 Flask 应用程序实例:
from flask import Flask from database import db app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:password@localhost:3306/ayangnote?charset=utf8' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app)- 在其他模块中导入 db 对象,并确保它们使用的是相同的 Flask 应用程序实例。例如,在 module.py 中:
from database import db with app.app_context(): class Users(db.Model): ...这样,所有模块都将使用相同的 Flask 应用程序实例和 SQLAlchemy 实例,从而避免出现不同实例之间的冲突。
最后鸣谢chatgpt,呜呜