# flask_app.py — 入口:app 创建 + 蓝图注册 + 迁移 + 启动 # 拆分后仅 ~35 行,所有路由在 routes.py,业务辅助在 helpers.py,基础设施在 db.py import os import sys # 确保 backend 目录在 sys.path 中(兼容 gunicorn --preload 模式) _backend_dir = os.path.dirname(os.path.abspath(__file__)) if _backend_dir not in sys.path: sys.path.insert(0, _backend_dir) from flask import Flask from db import ROOT # 触发 load_dotenv + 建目录 from routes import bp from migrations import run_migrations app = Flask( __name__, template_folder=str(ROOT / "templates"), static_folder=str(ROOT / "static"), ) # secret_key 必须从环境变量注入,禁止硬编码兜底——否则 session 可被伪造。 _secret_key = os.environ.get("SECRET_KEY") if not _secret_key: raise RuntimeError( "缺少必需的环境变量 SECRET_KEY,请在 .env 中配置(建议: " "python3 -c 'import secrets;print(secrets.token_hex(32))')" ) app.secret_key = _secret_key app.config["TEMPLATES_AUTO_RELOAD"] = True # 自动读取 git tag 作为版本号,保持左上角与发布 tag 一致 import subprocess as _sp def _git_version(): try: tags = _sp.check_output( ["git", "tag", "--sort=-v:refname"], cwd=_backend_dir, stderr=_sp.DEVNULL, ).decode().strip().split("\n") return tags[0] if tags and tags[0] else "dev" except Exception: return "dev" app.jinja_env.globals["app_version"] = _git_version() app.register_blueprint(bp) # 模块级执行迁移(保留 gunicorn --preload 行为:导入即触发) run_migrations() if __name__ == "__main__": app.run( host="127.0.0.1", port=5177, debug=os.environ.get("FLASK_DEBUG", "false").lower() in ("true", "1", "yes"), )