Flask工厂模式配置Flask Migrate时遇UnboundLocalError错误求助
Flask Migrate工厂模式配置错误解决
问题场景
采用工厂模式搭建Flask应用,配置Flask Migrate处理数据库迁移时,执行flask db init命令触发UnboundLocalError错误。
错误日志
Traceback (most recent call last): File "/Users/grahammorby/Documents/GitHub/tagr-api/venv/bin/flask", line 8, in <module> sys.exit(main()) ^^^^^^ File "/Users/grahammorby/Documents/GitHub/tagr-api/venv/lib/python3.12/site-packages/flask/cli.py", line 1064, in main cli.main() File "/Users/grahammorby/Documents/GitHub/tagr-api/venv/lib/python3.12/site-packages/click/core.py", line 1078, in main rv = self.invoke(ctx) ^^^^^^^^^^^^^^^^ File "/Users/grahammorby/Documents/GitHub/tagr-api/venv/lib/python3.12/site-packages/click/core.py", line 1682, in invoke cmd_name, cmd, args = self.resolve_command(ctx, args) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/grahammorby/Documents/GitHub/tagr-api/venv/lib/python3.12/site-packages/click/core.py", line 1729, in resolve_command cmd = self.get_command(ctx, cmd_name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/grahammorby/Documents/GitHub/tagr-api/venv/lib/python3.12/site-packages/flask/cli.py", line 579, in get_command app = info.load_app() ^^^^^^^^^^^^^^^ File "/Users/grahammorby/Documents/GitHub/tagr-api/venv/lib/python3.12/site-packages/flask/cli.py", line 313, in load_app app = locate_app(import_name, None, raise_if_not_found=False) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/grahammorby/Documents/GitHub/tagr-api/venv/lib/python3.12/site-packages/flask/cli.py", line 219, in locate_app __import__(module_name) File "/Users/grahammorby/Documents/GitHub/tagr-api/wsgi.py", line 3, in <module> app = init_app() ^^^^^^^^^^ File "/Users/grahammorby/Documents/GitHub/tagr-api/application/__init__.py", line 26, in init_app Migrate = Migrate(app, db) UnboundLocalError: cannot access local variable 'Migrate' where it is not associated with a value
应用初始化代码
from flask import Flask from config import Config from flask_sqlalchemy import SQLAlchemy from flask_marshmallow import Marshmallow from flask_bcrypt import Bcrypt from flask_jwt_extended import JWTManager from flask_migrate import Migrate # Global accessible libraries db = SQLAlchemy() ma = Marshmallow() bcrypt = Bcrypt() JWTManager = JWTManager() def init_app(): app = Flask(__name__, instance_relative_config=False) app.config.from_object(Config) # Setup plugins db.init_app(app) ma.init_app(app) bcrypt.init_app(app) JWTManager.init_app(app) Migrate = Migrate(app, db) from models import User, App with app.app_context(): # Blueprints from application.users import users_blueprint from application.apps import apps_blueprint app.register_blueprint(users_blueprint) app.register_blueprint(apps_blueprint) return app
错误原因
- 变量命名冲突:代码中
Migrate = Migrate(app, db)一行,全局导入的Migrate类和函数内的局部变量Migrate重名,Python解释器优先将其视为局部变量,赋值前引用就触发UnboundLocalError。 - 工厂模式配置错误:Flask Migrate在工厂模式下不能直接在函数内实例化,需遵循扩展的标准初始化流程——先全局创建空实例,再通过
init_app方法绑定应用。
解决方法
步骤1:统一全局扩展实例命名
修改全局变量部分,将类名和实例名区分开,创建空的Migrate实例:
# Global accessible libraries db = SQLAlchemy() ma = Marshmallow() bcrypt = Bcrypt() jwt = JWTManager() # 替换原JWTManager = JWTManager(),避免类名实例名冲突 migrate = Migrate() # 创建空的Migrate实例
步骤2:在init_app中初始化Migrate
修改init_app函数内的插件初始化代码,使用init_app方法绑定应用和数据库:
def init_app(): app = Flask(__name__, instance_relative_config=False) app.config.from_object(Config) # Setup plugins db.init_app(app) ma.init_app(app) bcrypt.init_app(app) jwt.init_app(app) migrate.init_app(app, db) # 用init_app方法初始化Migrate from models import User, App with app.app_context(): # Blueprints from application.users import users_blueprint from application.apps import apps_blueprint app.register_blueprint(users_blueprint) app.register_blueprint(apps_blueprint) return app
步骤3:设置FLASK_APP环境变量
执行迁移命令前,确保已指定正确的应用入口(假设入口为wsgi.py):
export FLASK_APP=wsgi.py export FLASK_ENV=development # 开发环境可选
步骤4:执行迁移命令
现在可正常执行数据库迁移操作:
flask db init flask db migrate -m "initial migration" flask db upgrade
内容的提问来源于stack exchange,提问作者Graham Morby
相关产品推荐
相关产品推荐

