全书目录

第二十九篇:Flask 完全指南 —— 轻骑兵微服务街区宇宙

第九章:应用工厂和蓝图 —— 真正能长大的 Flask,都不会一直单文件

2 分钟 471 字 第 526 / 962 个阅读单元

Flask 可以单文件起步,但官方教程也明确提醒:项目一长大,应该转向更结构化的方式。

一个能继续长大的 Flask 项目,通常会长这样:

text
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.py

riderhub/__init__.py

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 app

riderhub/missions.py

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 不是可插拔独立应用,它更像一份“注册时执行的图纸”。

你可以把它理解成:

text
Flask app   = 整个轻骑兵街区司令部
Blueprint   = 某个分街区的施工图与哨站注册表

Blueprint 可以:

  • 挂自己的路由
  • 挂自己的模板
  • 挂自己的静态资源
  • 注册自己的 error handler
  • 挂在不同 url_prefix

但 Blueprint 不是独立运行体。 它必须被注册到 app 上才真正生效。

还有一个经常被忽略的事实:

Blueprint 一旦注册进 app,就不是拿出来就能“反注册”的。 要变更,通常得重建应用对象。