首次搭建Flask工厂模式遇ImportError:循环导入致无法导入db
解决Flask工厂模式下的循环导入错误
错误信息
Traceback (most recent call last): 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 1, in <module> from application import init_app File "/Users/grahammorby/Documents/GitHub/tagr-api/application/__init__.py", line 9, in <module> from application.users import users_blueprint File "/Users/grahammorby/Documents/GitHub/tagr-api/application/users.py", line 3, in <module> from application.models import User File "/Users/grahammorby/Documents/GitHub/tagr-api/application/models.py", line 2, in <module> from . import db, ma ImportError: cannot import name 'db' from partially initialized module 'application' (most likely due to a circular import) (/Users/grahammorby/Documents/GitHub/tagr-api/application/__init__.py)
项目文件内容
wsgi.py
from application import init_app app = init_app() if __name__ == "__main__": app.run(host='0.0.0.0')
初始版本 application/__init__.py
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 application.users import users_blueprint from application.apps import apps_blueprint # Globally 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) with app.app_context(): # Blueprints return app
application/models.py
from sqlalchemy import Column, Integer, String from . import db, ma class App(db.model): __tablename__ = "apps" id = Column(Integer, primary_key=True) app_name = Column(String(64)) icon = Column(String(255)) class AppSchema(ma.Schema): class Meta: fields = ("id", "app_name", "icon") app_schema = AppSchema() apps_schema = AppSchema(many=True)
修改后仍有问题的 application/__init__.py
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 = init_app(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
解决方案
核心问题
循环导入的根源是模块级导入顺序冲突:__init__.py在模块顶部导入蓝图,蓝图依赖models.py,而models.py需要导入__init__.py中尚未完成定义的db/ma实例,导致模块初始化卡住。
具体修复步骤
调整导入位置,避免模块级循环
将蓝图、models的导入从__init__.py的模块顶部,移到init_app函数内部,且放在插件初始化之后、app上下文环境中。确保db/ma等实例完全初始化后,再导入依赖它们的模块。修正models.py的笔误
将class App(db.model):改为class App(db.Model):(注意Model首字母大写),否则会触发属性不存在的错误。规范插件实例命名
不要用插件类名作为实例变量名(如原代码中的JWTManager = JWTManager()),避免命名冲突,改为jwt = JWTManager()。
修正后的代码
application/__init__.py
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 # 仅在模块级别定义插件实例,不导入内部模块 db = SQLAlchemy() ma = Marshmallow() bcrypt = Bcrypt() jwt = JWTManager() migrate = Migrate() def init_app(): app = Flask(__name__, instance_relative_config=False) app.config.from_object(Config) # 初始化所有插件 db.init_app(app) ma.init_app(app) bcrypt.init_app(app) jwt.init_app(app) migrate.init_app(app, db) with app.app_context(): # 先导入models,确保db已初始化 from application import models # 再导入并注册蓝图 from application.users import users_blueprint from application.apps import apps_blueprint app.register_blueprint(users_blueprint) app.register_blueprint(apps_blueprint) return app
application/models.py
from sqlalchemy import Column, Integer, String from . import db, ma class App(db.Model): __tablename__ = "apps" id = Column(Integer, primary_key=True) app_name = Column(String(64)) icon = Column(String(255)) class AppSchema(ma.Schema): class Meta: fields = ("id", "app_name", "icon") app_schema = AppSchema() apps_schema = AppSchema(many=True)
验证修复
启动应用后,循环导入错误会消失,同时models中的笔误也被修正,确保数据库模型能正常工作。
内容的提问来源于stack exchange,提问作者Graham Morby
相关产品推荐
相关产品推荐

