Flask 可以单文件起步,但官方教程也明确提醒:项目一长大,应该转向更结构化的方式。
一个能继续长大的 Flask 项目,通常会长这样:
riderhub/
├── pyproject.toml
├── instance/
├── riderhub/
│ ├── __init__.py
│ ├── db.py
│ ├── auth.py
│ ├── missions.py
│ ├── templates/
│ │ ├── base.html
│ │ └── missions/
│ │ └── list.html
│ └── static/
│ └── app.css
└── tests/
├── conftest.py
└── test_missions.pyriderhub/__init__.py:
from flask import Flask
def create_app(test_config=None):
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(SECRET_KEY="dev")
if test_config is not None:
app.config.update(test_config)
from . import db
db.init_app(app)
from .missions import bp as missions_bp
app.register_blueprint(missions_bp)
@app.get("/healthz")
def healthz():
return {"status": "ok"}
return appriderhub/missions.py:
from flask import Blueprint, jsonify, request
bp = Blueprint("missions", __name__, url_prefix="/missions")
@bp.get("/")
def list_missions():
status = request.args.get("status")
return jsonify([
{"id": 1, "name": "巡逻西门", "status": status or "ready"}
])
@bp.post("/")
def create_mission():
data = request.get_json() or {}
return {"id": 2, "name": data.get("name", "未命名任务")}, 201这里有两个必须形成硬认知的点。
第一,应用工厂不是“高级写法”,而是大项目常规写法。
它的好处很明确:
- 测试时可以创建不同配置的 app
- 一个进程里可以创建多个 app 实例
- 更容易做插件化和环境隔离
第二,Blueprint 不是 app。
官方文档说得很清楚,Blueprint 不是可插拔独立应用,它更像一份“注册时执行的图纸”。
你可以把它理解成:
Flask app = 整个轻骑兵街区司令部
Blueprint = 某个分街区的施工图与哨站注册表Blueprint 可以:
- 挂自己的路由
- 挂自己的模板
- 挂自己的静态资源
- 注册自己的 error handler
- 挂在不同
url_prefix下
但 Blueprint 不是独立运行体。 它必须被注册到 app 上才真正生效。
还有一个经常被忽略的事实:
Blueprint 一旦注册进 app,就不是拿出来就能“反注册”的。 要变更,通常得重建应用对象。