Flask、SQLAlchemy和Migrate

flask-sql_alchemy和flask-migrate在 Flask + 数据库 体系里几乎是“标配搭子”,如果把开发 Web 应用比作盖房子,那么 SQLAlchemy 就是施工图纸和建筑材料,而 Flask-Migrate 就是装修进度管理手册。

Flask 与 SQLAlchemy 的“神仙搭档”

1 Flask

在谈SQLAlchemy之前,需要先了解Flask。Flask 是一个用 Python 编写的 微框架(Microframework)。它的核心设计哲学是“保持简单,易于扩展”:

  • 轻量: 它只提供 Web 开发的核心功能(路由、请求处理、模板引擎),不强制你使用特定的数据库或账号系统。
  • 灵活: 你可以自由选择喜欢的工具(比如用 SQLAlchemy 连数据库,用 WTForms 搞表单)。
  • 易上手: 几行代码就能跑起一个 Web 服务器。

2 SQLAlchemy

SQLAlchemy 是一个功能强大的 ORM(对象关系映射) 库。

  • 核心功能: 让你用 Python 类来操作数据库,而不是写原生的 SQL 语句。
  • 它的职责:
    • 映射: 把 Python 的类映射成数据库里的表,把类实例映射成表里的一行数据。
    • 抽象: 你不需要关心底层是 MySQL、PostgreSQL 还是 SQLite,SQLAlchemy 会帮你翻译成对应的语法。
    • 操作: 增删改查(CRUD)全部通过 Python 方法完成,例如 user.save()User.query.all()

3 Flask和SQLAlchemy

在 Flask 中,我们通常使用它的扩展版 Flask-SQLAlchemy这个扩展插件与 SQLAlchemy 深度集成。

Flask-SQLAlchemy = SQLAlchemy + Flask 适配层

它帮开发者解决了:

  • 数据库连接生命周期
  • app / request 上下文绑定
  • session 管理
  • 简化配置

它们之间的搭配就像是 “大脑”与“管家” 的关系:

1. 结构上的互补

  • Flask (大脑): 负责接收用户的 HTTP 请求(比如:用户点击了“注册”按钮),并决定返回什么页面。
  • SQLAlchemy (管家): 负责处理繁琐的数据库交互。大脑告诉它“存一下这个用户信息”,管家就去处理 SQL 语句并和数据库对接。

2. 开发模式:模型驱动

在 Flask 项目中,你不需要去数据库里敲 CREATE TABLE。你会通过 SQLAlchemy 定义一个 Model(模型)

Python

# 这是一个典型的 Flask-SQLAlchemy 模型定义
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True)

这样一来,就可以用 Python 对象的方式操作数据库,而不是手写 SQL。

3. 数据流转过程

当一个请求进来时,它们的协作流程如下:

  1. 路由接收 (Flask): 用户访问 /profile/1
  2. 查询数据 (SQLAlchemy): Flask 调用 User.query.get(1)。SQLAlchemy 自动将其翻译成 SELECT * FROM user WHERE id = 1
  3. 返回结果: SQLAlchemy 返回一个 Python 对象,Flask 将其中的数据塞进 HTML 模板展示给用户。

4 核心配置示例

要把它们配成对,通常只需要三步:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
# 1. 告诉 Flask 数据库在哪里
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
# 2. 初始化插件
db = SQLAlchemy(app)

# 这是一个典型的 Flask-SQLAlchemy 模型定义
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True)
    
# 3. 愉快地使用!
@app.route('/')
def index():
    users = User.query.all() # 直接调用模型查询
    return f"总共有 {len(users)} 个用户"

Flask-Migrate: 数据库的“后悔药” (Migration)

虽然 SQLAlchemy 可以帮你创建表(通过 db.create_all()),但它有一个致命弱点:它不会更新表。如果你给 User 类增加了一个 email 字段,db.create_all() 会直接忽略它,除非你删掉数据库重新来。

这就是 Flask-Migrate 出场的时候了,它是是数据库「版本管理 / 迁移工具:

  • 核心功能: 基于 Alembic 引擎,Alembic 是 SQLAlchemy 官方的迁移工具,记录数据库结构的所有变更。
  • 它的职责:
    • 版本控制: 就像 Git 管理代码一样,它管理数据库的 Schema(模式)。
    • 平滑升级: 在保留数据库现有数据的情况下,增加字段、修改约束或删除列。
    • 回滚: 如果这次改动导致程序崩了,你可以一键“撤销”回到上一个版本。

1 Flask-Migrate运行过程

当你输入那些 flask db 命令时,可以拆解为四个关键阶段。

1. 初始化阶段:建立仓库 (init)

执行命令: flask db init

执行 flask db init 后会在项目中创建数据库迁移相关的文件结构,即在你的项目根目录下创建一个migrations 目录,其中包含:

  • versions/ - 存放迁移脚本的目录
  • alembic.ini - Alembic 配置文件
  • env.py - 迁移环境配置
  • script.py.mako - 迁移脚本模板

这些文件会被 Flask-Migrate (基于 Alembic) 用来:跟踪数据库 schema 的变化、生成迁移脚本、管理数据库版本

2. 检测阶段:发现差异 (migrate)

执行命令: flask db migrate -m "说明文字"

这是最核心的一步,它的运行逻辑如下:

  1. 扫描模型: Flask-Migrate 会去查看你代码里定义的 SQLAlchemy 模型(即那些继承自 db.Model 的类)。
  2. 查看数据库: 检查数据库当前的状态(它会查看数据库中一个叫 alembic_version 的特殊表)。
  3. 计算差值(Diff): 对比两者的结构。比如,你在模型里增加了一个 phone 字段,但数据库表里没有。
  4. 生成脚本: 自动在 migrations/versions/ 下生成一个 Python 脚本。这个脚本包含两个函数:
    • upgrade(): 描述如何把数据库升级到新版本(例如:op.add_column(...))。
    • downgrade(): 描述如何撤销这次改动(例如:op.drop_column(...))。

3. 执行阶段:物理改动 (upgrade)

执行命令: flask db upgrade

这一步才是真正“动刀子”修改数据库表结构的时候。

  • 动作: 读取最新的迁移脚本,执行其中的 upgrade() 函数。
  • 结果: 数据库表结构被修改。同时,数据库里的 alembic_version 表会更新为一个新的哈希值(版本号),确保下次迁移时知道从哪开始。

4. 撤销阶段:时空回溯 (downgrade)

执行命令: flask db downgrade

如果你发现刚才的改动有问题(比如删错了字段),可以使用这个命令。

  • 动作: 执行脚本中的 downgrade() 函数。
  • 结果: 数据库回退到上一个版本。

2 常见问题

1. 模型类没有正确导入

有时候修改了模型,运行 migrate 却提示 “No changes detected”。 这通常是因为:

  1. 忘记在 app.py 或初始化的地方 import 你的模型类,导致 Flask-Migrate 没能发现它们。
  2. 没有正确设置 db = SQLAlchemy(app) 中的 app 上下文。

在执行flask db命令前,需要保证所有的模型类被 Python 先加载到内存中。这就是为什么通常建议在model模块的 __init__.py 中导入所有模型,以确保它们在应用启动时就被正确注册。


  本篇
Flask、SQLAlchemy和Migrate Flask、SQLAlchemy和Migrate
flask-sql_alchemy和flask-migrate在 Flask + 数据库 体系里几乎是“标配搭子”,如果把开发 Web 应用比作盖房子,那么 SQLAlchemy 就是施工图纸和建筑材料,而 Flask-Migrate 就是装修进度管理手册。
2024-09-13
下一篇 
LLM中的Tokenizer LLM中的Tokenizer
在现代计算语言学和大规模语言模型(LLM)的架构体系中,分词器(Tokenizer)是连接人类自然语言与机器数值计算的唯一底层接口。
2024-08-28
   目录