【切尾】 - src/app.py:应用工厂(原 application/factory.py) - src/extensions.py:扩展注册编排(原 extensions/) - src/wsgi.py:生产 WSGI 入口 - 根 app.py 改为 from src.app import create_app(开发入口保留) - gunicorn/Docker/compose 指向 src.wsgi:app - 删除 application/、extensions/、utils/(全部代码已迁入 src/) 【清理】21 个 router 中间件导入改 src.core;修复 level 服务潜在 bug (utils.load2dict 不存在 → model_to_dict);测试文件 R 导入改 src.core 【里程碑】全项目 flake8 从 P1 基线 154 条 → **0 条**; 12 passed;app.py 与 src.wsgi 双入口均启动 Co-Authored-By: Claude <noreply@anthropic.com>
171 lines
6.8 KiB
Python
171 lines
6.8 KiB
Python
# +======================================================================
|
||
# | DjangoAdmin 企业数字化开发平台 [ 赋能开发者,助力企业发展 ]
|
||
# +----------------------------------------------------------------------
|
||
# | Copyright (c) 2021-2026 一米阳光团队 版权所有
|
||
# +----------------------------------------------------------------------
|
||
# | 开源协议: Apache-2.0
|
||
# | 重要声明: 未经书面许可,不得移除或修改本框架相关版权标识。
|
||
# +----------------------------------------------------------------------
|
||
# | 官方网站: https://www.djangoadmin.cn
|
||
# +----------------------------------------------------------------------
|
||
# | 研发团队: 一米阳光团队 荣誉出品
|
||
# +======================================================================
|
||
|
||
"""
|
||
数据库配置模块
|
||
=============================================================
|
||
|
||
负责配置 MySQL 数据库连接及相关参数,包含连接池、SSL 加密等。
|
||
依赖:config/__init__.py 中的 _load_env_file() 已提前加载 .env
|
||
"""
|
||
|
||
import os
|
||
from urllib.parse import quote_plus
|
||
from config.app import FLASK_SECRET_KEY, FLASK_UPLOAD_DIR
|
||
|
||
# ============================================================
|
||
# 数据库环境变量
|
||
# ============================================================
|
||
|
||
# 数据库驱动(mysql / pgsql / sqlite)
|
||
DB_DRIVER = os.getenv('DB_DRIVER', 'mysql')
|
||
# 数据库地址
|
||
DB_HOST = os.getenv('DB_HOST', '127.0.0.1')
|
||
# 数据库端口(MySQL默认3306,PostgreSQL默认5432)
|
||
DB_PORT = int(os.getenv('DB_PORT', 3306))
|
||
# 数据库名称
|
||
DB_DATABASE = os.getenv('DB_DATABASE', 'djangoadmin.flask.elevue')
|
||
# 数据库账号
|
||
DB_USERNAME = os.getenv('DB_USERNAME', 'root')
|
||
# 数据库密码
|
||
DB_PASSWORD = os.getenv('DB_PASSWORD', '')
|
||
# 数据表前缀(用于区分同一数据库中不同应用的数据表)
|
||
DB_PREFIX = os.getenv('DB_PREFIX', 'flask_')
|
||
# 是否开启调试模式:True-打印SQL日志,False-不打印
|
||
DB_DEBUG = os.getenv('DB_DEBUG', 'True') == 'True'
|
||
# 是否启用数据库SSL加密连接(生产环境建议开启,防止数据明文传输)
|
||
DB_SSL = os.getenv('DB_SSL', 'False') == 'True'
|
||
# SSL CA证书路径(用于验证服务端证书,留空则信任系统CA)
|
||
DB_SSL_CA = os.getenv('DB_SSL_CA', '')
|
||
# SSL 客户端证书路径(双向认证时使用)
|
||
DB_SSL_CERT = os.getenv('DB_SSL_CERT', '')
|
||
# SSL 客户端私钥路径(双向认证时使用)
|
||
DB_SSL_KEY = os.getenv('DB_SSL_KEY', '')
|
||
|
||
# ============================================================
|
||
# 连接池配置
|
||
# ============================================================
|
||
|
||
# 连接池常驻连接数(默认10,生产环境建议根据并发量调整)
|
||
DB_POOL_SIZE = int(os.getenv('DB_POOL_SIZE', 10))
|
||
# 超出pool_size后允许的最大额外连接(默认10,总连接数=pool_size+max_overflow)
|
||
DB_MAX_OVERFLOW = int(os.getenv('DB_MAX_OVERFLOW', 10))
|
||
# 连接自动回收时间/秒(默认1800,应小于MySQL的wait_timeout,防止"MySQL server has gone away")
|
||
DB_POOL_RECYCLE = int(os.getenv('DB_POOL_RECYCLE', 1800))
|
||
# 获取连接的超时时间/秒(默认30,超时抛出TimeoutError)
|
||
DB_POOL_TIMEOUT = int(os.getenv('DB_POOL_TIMEOUT', 30))
|
||
# 使用前是否检测连接存活(默认True,防止使用已被MySQL关闭的连接)
|
||
DB_POOL_PRE_PING = os.getenv('DB_POOL_PRE_PING', 'True') == 'True'
|
||
|
||
# 数据库连接URL(方便SQLAlchemy直接使用)
|
||
DATABASE_URL = f'mysql+pymysql://{quote_plus(DB_USERNAME)}:{quote_plus(DB_PASSWORD)}@{DB_HOST}:{DB_PORT}/{DB_DATABASE}'
|
||
|
||
|
||
def _build_engine_options():
|
||
"""
|
||
构建SQLAlchemy引擎选项
|
||
|
||
包含连接池配置和SSL加密配置。
|
||
连接池参数通过SQLALCHEMY_ENGINE_OPTIONS传递,
|
||
确保所有连接管理策略集中在一处。
|
||
"""
|
||
options = {
|
||
'pool_size': DB_POOL_SIZE,
|
||
'max_overflow': DB_MAX_OVERFLOW,
|
||
'pool_recycle': DB_POOL_RECYCLE,
|
||
'pool_timeout': DB_POOL_TIMEOUT,
|
||
'pool_pre_ping': DB_POOL_PRE_PING,
|
||
}
|
||
if DB_SSL:
|
||
ssl_config = {}
|
||
if DB_SSL_CA:
|
||
ssl_config['ca'] = DB_SSL_CA
|
||
if DB_SSL_CERT:
|
||
ssl_config['cert'] = DB_SSL_CERT
|
||
if DB_SSL_KEY:
|
||
ssl_config['key'] = DB_SSL_KEY
|
||
# 无证书路径时使用默认SSL(信任系统CA)
|
||
if not ssl_config:
|
||
ssl_config = True
|
||
options['connect_args'] = {'ssl': ssl_config}
|
||
return options
|
||
|
||
|
||
class DatabaseConfig:
|
||
"""
|
||
数据库配置类
|
||
|
||
包含 MySQL 连接、SQLAlchemy 设置、路径等配置
|
||
"""
|
||
|
||
# ============================================================
|
||
# 基础配置
|
||
# ============================================================
|
||
|
||
# 调试模式(从环境变量读取)
|
||
DEBUG = DB_DEBUG
|
||
|
||
# Flask 秘钥(用于 session 加密等)
|
||
# 启动时校验:未配置或过短则拒绝启动
|
||
if not FLASK_SECRET_KEY or len(FLASK_SECRET_KEY) < 16:
|
||
raise RuntimeError(
|
||
"FLASK_SECRET_KEY 未配置或过短!请在 .env 中设置至少16字节的强随机密钥。\n"
|
||
"生成方式:python -c \"import secrets; print(secrets.token_hex(32))\""
|
||
)
|
||
SECRET_KEY = FLASK_SECRET_KEY
|
||
|
||
# ============================================================
|
||
# CSRF 防护配置
|
||
# ============================================================
|
||
|
||
# 本项目使用 JWT(Authorization 头)认证,非 Cookie/Session,
|
||
# 天然防 CSRF,因此 WTForms CSRF 保护无需开启。
|
||
WTF_CSRF_CHECK_DEFAULT = False
|
||
WTF_CSRF_ENABLED = False
|
||
|
||
# ============================================================
|
||
# MySQL 数据库配置
|
||
# ============================================================
|
||
|
||
# 构建 MySQL 连接 URI(使用 PyMySQL 驱动)
|
||
SQLALCHEMY_DATABASE_URI = (
|
||
f'mysql+pymysql://{quote_plus(DB_USERNAME)}:{quote_plus(DB_PASSWORD)}@'
|
||
f'{DB_HOST}:{DB_PORT}/{DB_DATABASE}'
|
||
)
|
||
# 不追踪对象修改(提升性能)
|
||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||
# 是否打印 SQL 语句(调试模式下开启)
|
||
SQLALCHEMY_ECHO = DB_DEBUG
|
||
# 数据库连接引擎选项(连接池 + SSL加密)
|
||
SQLALCHEMY_ENGINE_OPTIONS = _build_engine_options()
|
||
|
||
# ============================================================
|
||
# 路径配置
|
||
# ============================================================
|
||
|
||
# 配置目录路径
|
||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||
# 静态文件目录
|
||
STATIC_DIR = os.path.join(BASE_DIR, '../static')
|
||
# 模板文件目录
|
||
TEMPLATE_DIR = os.path.join(BASE_DIR, '../templates')
|
||
# 文件上传目录
|
||
FLASK_UPLOAD_DIR = FLASK_UPLOAD_DIR
|
||
|
||
|
||
# 模块测试入口
|
||
if __name__ == '__main__':
|
||
print(f"数据库连接: {DatabaseConfig.SQLALCHEMY_DATABASE_URI}")
|
||
print(f"调试模式: {DatabaseConfig.DEBUG}")
|
||
print(f"文件上传目录: {DatabaseConfig.FLASK_UPLOAD_DIR}")
|