使用Flask Blueprint拆分代码后出现SQLAlchemy RuntimeError求助
问题
我用Flask开发了一套登录注册程序,单文件app.py运行正常,但用Blueprint拆分代码后出现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?
项目结构:
main app.py templates index.html instance users.db auth __init__.py auth.py models.py templates login.html register.html home __init__.py home.py templates dashboard.html
相关代码:
main/app.py
from flask import Flask, render_template from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate import secrets db = SQLAlchemy() migate = Migrate() def create_app(): app = Flask(__name__) app.config['SECRET_KEY'] = secrets.token_hex(16) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) migate.init_app(app, db) from auth.auth import auth as auth_blueprint from home.home import home as home_blueprint app.register_blueprint(auth_blueprint) app.register_blueprint(home_blueprint) @app.route('/') def index(): return render_template('index.html') return app if __name__ == '__main__': app = create_app() with app.app_context(): db.create_all() app.run(debug=True)
main/auth/init.py
from flask import Blueprint auth = Blueprint("auth", __name__, template_folder="templates")
main/auth/auth.py
from flask import render_template, redirect, request, session from auth.models import User from datetime import datetime from app import db from auth import auth import hashlib import re @auth.route('/test') @auth.route('/register', methods=['GET', 'POST']) def register(): if request.method == 'POST': name = request.form['name'] username = request.form['username'] password = request.form['password'] email = request.form['email'] birth = str(request.form['birth']) ... if not checkDupId(username): return render_template('register.html', error) ... def checkDupId(user_id): dup_user_id = User.query.filter_by(username=user_id).first() # 此代码报错 if dup_user_id is not None: return False else: return True @auth.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] user = User.query.filter_by( username=username, password=hash_password(password)).first() # 此代码也报错 ...
main/auth/models.py
from app import db class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(30), nullable=False) username = db.Column(db.String(50), unique=True, nullable=False) password = db.Column(db.String(64), nullable=False) email = db.Column(db.String(50), nullable=True) birth = db.Column(db.Date, nullable=False)
问题原因与解决办法
核心原因
你用应用工厂模式时,auth模块导入的db和模型没有正确关联到create_app()创建的Flask应用实例:
- 模块加载阶段就从
app导入db,此时create_app()还未运行,db没通过init_app()绑定到应用。 - 执行数据库查询时,当前请求上下文的应用实例和
db实例无绑定关系,触发报错。
解决步骤
1. 独立存放扩展实例,避免循环依赖
新建main/extensions.py文件,专门管理Flask扩展:
# main/extensions.py from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate db = SQLAlchemy() migrate = Migrate()
修改main/app.py,从extensions导入扩展:
# main/app.py from flask import Flask, render_template from extensions import db, migrate import secrets def create_app(): app = Flask(__name__) app.config['SECRET_KEY'] = secrets.token_hex(16) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db.init_app(app) migrate.init_app(app, db) # 延迟导入蓝图,避免循环依赖 from auth.auth import auth as auth_blueprint from home.home import home as home_blueprint app.register_blueprint(auth_blueprint) app.register_blueprint(home_blueprint) @app.route('/') def index(): return render_template('index.html') return app if __name__ == '__main__': app = create_app() with app.app_context(): db.create_all() app.run(debug=True)
2. 更新auth模块的导入路径
修改main/auth/models.py:
# main/auth/models.py from extensions import db class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(30), nullable=False) username = db.Column(db.String(50), unique=True, nullable=False) password = db.Column(db.String(64), nullable=False) email = db.Column(db.String(50), nullable=True) birth = db.Column(db.Date, nullable=False)
修改main/auth/auth.py的db导入:
# main/auth/auth.py from flask import render_template, redirect, request, session from auth.models import User from datetime import datetime from extensions import db # 替换原有的from app import db from auth import auth import hashlib import re # 其余代码保持不变
3. 确保操作在应用上下文内执行
如果有在请求上下文外执行数据库操作的场景(比如初始化脚本),必须手动激活应用上下文,就像app.py里的with app.app_context():写法。
额外修正
你代码里的migate是拼写错误,正确应为migrate,已在修正代码中调整,避免后续运行报错。
内容的提问来源于stack exchange,提问作者Y SW
相关产品推荐
相关产品推荐

