Flask如何从应用配置读取参数加载数据库
解决方案
核心问题是你当前在database.py顶层就执行了数据库引擎创建,这个导入时机早于Flask应用实例化、配置加载的阶段,自然读不到配置。解决思路是把数据库连接初始化逻辑延后到配置加载完成后执行,也就是放到应用工厂函数的流程里。
1. 重构database.py
移除顶层硬编码的引擎实例化代码,改为提供初始化函数,全局会话、引擎变量先声明后赋值:
from sqlalchemy import create_engine from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy.ext.declarative import declarative_base # 全局占位变量 engine = None db_session = None Base = declarative_base() def init_db(app): global engine, db_session # 此时app配置已加载完成,直接从配置读取数据库URI engine = create_engine(app.config["SQLALCHEMY_DATABASE_URI"]) db_session = scoped_session( sessionmaker(autocommit=False, autoflush=False, bind=engine) ) Base.query = db_session.query_property() # 注册钩子,请求结束后自动关闭会话 @app.teardown_appcontext def shutdown_session(exception=None): db_session.remove()
2. 修改应用工厂逻辑(app/init.py)
修正原有代码的缩进错误(原代码return myapp缩进在函数外会直接报错),在配置加载完成后调用数据库初始化函数:
from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate # 顶层只导入初始化方法,不导入未实例化的db_session from app.database import init_db db = SQLAlchemy() migrate = Migrate() def create_app(): myapp = Flask( __name__, static_folder="static", static_url_path="/static", template_folder="templates" ) # 第一步先加载配置 myapp.config.from_object("config.Config") # 配置加载完成后再初始化数据库连接 init_db(myapp) db.init_app(myapp) migrate.init_app(myapp, db) # 注册蓝图 from app.core_bp import core_bp myapp.register_blueprint( core_bp, url_prefix="/", template_folder="templates" ) return myapp
3. 添加配置项
在你的配置类config.Config中增加数据库URI配置即可,后续修改数据库路径只需要改配置,不需要动业务代码:
import os class Config: # 其他原有配置项保持不变 SQLALCHEMY_DATABASE_URI = "sqlite:///" + os.path.join( os.path.abspath(os.path.dirname(__file__)), "rapporteur.db" ) SQLALCHEMY_TRACK_MODIFICATIONS = False
使用说明
后续在模型、蓝图中需要操作数据库时,直接导入db_session使用即可:
from app.database import db_session
只要相关逻辑是在create_app()执行完成、应用启动后触发的,拿到的会话都会绑定配置中指定的数据库路径,不会出现空值或连接错库的问题。
如果你全程使用Flask-SQLAlchemy提供的
db对象操作数据库,不需要自己实现scoped_session、init_db逻辑:Flask-SQLAlchemy会在db.init_app(myapp)时自动读取当前app配置中的SQLALCHEMY_DATABASE_URI创建连接,只要保证init_app调用在配置加载之后就不会有硬编码问题。
内容的提问来源于stack exchange,提问作者rapsli
相关产品推荐
相关产品推荐

