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

Flask项目分离数据库Schema与API接口时遇循环导入错误求助

解决Flask模型与API代码拆分的循环导入问题

循环导入的核心原因是:原代码中db对象在app.py里创建,模型需要导入db,而API路由又需要导入模型,同时app.py直接导入模型时会形成双向依赖。以下是具体的拆分方案:

项目结构调整

拆分后项目结构如下:

your_project/
├── app.py       # 应用初始化、路由定义
├── models.py    # 数据库模型定义
└── .env         # 环境变量配置

1. 编写models.py文件

将所有数据库模型移到该文件,单独初始化db对象,不依赖Flask app:

from flask_sqlalchemy import SQLAlchemy

# 先初始化db对象,后续在app中关联
db = SQLAlchemy()

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(50), unique=True, nullable=False)
    # 注意:密码哈希后的长度远大于50,这里修改为255避免存储截断
    password = db.Column(db.String(255), nullable=False)

class Customer(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), nullable=False)
    email = db.Column(db.String(120), nullable=False)
    phone = db.Column(db.String(120), nullable=False)

2. 重构app.py文件

使用应用工厂模式,在函数内部完成app配置、db初始化和路由注册,避免顶级作用域的循环导入:

import os
from dotenv import load_dotenv
from flask import Flask, jsonify, request
from flask_jwt_extended import JWTManager, create_access_token, create_refresh_token
from werkzeug.security import check_password_hash
from flask_cors import CORS
from datetime import timedelta
# 从models.py导入db和需要的模型
from models import db, User

load_dotenv()

def create_app():
    # 初始化Flask app
    app = Flask(__name__)
    app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('SQLALCHEMY_DATABASE_URI')
    app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY')
    
    # 将db与当前app关联
    db.init_app(app)
    
    # 初始化CORS和JWT
    CORS(app)
    JWTManager(app)
    
    # 注册路由
    register_routes(app)
    
    return app

def register_routes(app):
    # 登录路由
    @app.route('/login', methods=['POST'])
    def login():
        username = request.json.get('username', '')
        password = request.json.get('password', '')
        user = User.query.filter_by(username=username).first()

        if user and check_password_hash(user.password, password):
            access_token = create_access_token(identity=username, fresh=True, expires_delta=timedelta(minutes=30))
            refresh_token = create_refresh_token(identity=username)
            return jsonify(access_token=access_token, refresh_token=refresh_token), 200
        
        return jsonify({"message": "Invalid credentials"}), 401

if __name__ == '__main__':
    app = create_app()
    # 在app上下文里创建数据库表(首次运行需要)
    with app.app_context():
        db.create_all()
    app.run(debug=True)

方案原理

  • 把db对象的创建与Flask app的初始化分离,消除模型对app的直接依赖
  • 应用工厂函数create_app()在内部完成所有组件的初始化,避免顶级作用域的交叉导入
  • 路由单独放在register_routes函数中,确保只有在app创建完成后才导入模型,打破循环依赖链

内容的提问来源于stack exchange,提问作者Will

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 18:43:17