全书目录

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

第十二章:数据访问、CLI 命令、扩展模式 —— Flask 本体只给路,不给整套后勤

1 分钟 294 字 第 529 / 962 个阅读单元

Flask 本身不内置 ORM,不内置迁移系统,也不内置用户模型和后台。

这不是缺点,而是它的设计边界。

官方教程给出的纯 Flask 做法,是自己写数据库访问模块,再通过 g 和 CLI 命令组织:

py
import click
import sqlite3
from flask import current_app, g

def get_db():
    if "db" not in g:
        g.db = sqlite3.connect(current_app.config["DATABASE"])
        g.db.row_factory = sqlite3.Row
    return g.db

def close_db(e=None):
    db = g.pop("db", None)
    if db is not None:
        db.close()

def init_db():
    db = get_db()
    with current_app.open_resource("schema.sql") as f:
        db.executescript(f.read().decode("utf-8"))

@click.command("init-db")
def init_db_command():
    init_db()
    click.echo("initialized the database")

def init_app(app):
    app.teardown_appcontext(close_db)
    app.cli.add_command(init_db_command)

然后你就可以:

bash
flask --app riderhub init-db

这说明 Flask 的思路是:

核心框架只负责把街区调度好,具体后勤仓库和工兵系统,由你自己选。

如果你接扩展,官方又推荐另一条重要模式:

扩展对象先创建,但别在导入时就和 app 绑死,要用 init_app

以常见 ORM 扩展模式为例:

py
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app():
    app = Flask(__name__)
    app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///riderhub.db"
    db.init_app(app)
    return app

而不是这样:

py
db = SQLAlchemy(app)  # 不推荐在大型项目里这么早硬绑定

这个模式的好处是:

  • 测试更好做
  • 多 app 实例更好做
  • 结构更清楚
  • 扩展对象不携带某个具体 app 的粘连状态