You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

错误原因

  1. 变量命名冲突:代码中Migrate = Migrate(app, db)一行,全局导入的Migrate类和函数内的局部变量Migrate重名,Python解释器优先将其视为局部变量,赋值前引用就触发UnboundLocalError。
  2. 工厂模式配置错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 00:17:50