Aerich 是专为 Tortoise-ORM 设计的数据库迁移工具,灵感来源于 Django 的 South / migrations,目标是提供类似 Alembic(SQLAlchemy)的功能,但更贴合 Tortoise 的异步生态。
🧰 一、Aerich 是什么?
- 作用:自动检测模型变更 → 生成迁移脚本 → 安全地同步数据库 schema
特点:
- 原生支持 Tortoise-ORM 模型
- 支持 PostgreSQL / MySQL / SQLite
- 自动生成
upgrade()和downgrade()方法 - 支持初始建表、字段增删改、索引、唯一约束等
- 适用场景:FastAPI / Starlette 等异步框架 + Tortoise-ORM 项目
✅ 类比:
- SQLAlchemy → Alembic
- Django ORM → Django Migrations
- Tortoise-ORM → Aerich
🚀 二、安装 Aerich
pip install aerich⚠️ 要求:
- Python ≥ 3.7
- Tortoise-ORM ≥ 0.17.0
- 数据库驱动已安装(如
aiomysql,asyncpg,aiosqlite)
📁 三、项目结构准备
假设你的项目结构如下:
myapp/
├── main.py
├── models.py # Tortoise 模型定义
├── config.py # 数据库配置
└── migrations/ # ← Aerich 会自动生成此目录示例 config.py(包含 Tortoise 配置)
# config.py
TORTOISE_ORM = {
"connections": {
"default": "mysql://root:password@127.0.0.1:3306/mydb?charset=utf8mb4"
# 或 PostgreSQL: "postgres://user:pass@localhost:5432/mydb"
# 或 SQLite: "sqlite://db.sqlite3"
},
"apps": {
"models": {
"models": ["models", "aerich.models"], # 注意:包含 aerich.models
"default_connection": "default",
}
}
}🔥 关键:必须在models列表中加入"aerich.models",否则迁移记录表无法创建!
🛠 四、初始化 Aerich
在项目根目录执行:
aerich init -t config.TORTOISE_ORM-t:指定 Tortoise 配置路径(模块.变量名)执行后会生成:
migrations/目录migrations/models/子目录(存放模型快照)aerich.ini配置文件(可选)
✅ 成功提示:
Success create migrations folder migrations and config file aerich.ini.🔄 五、使用 Aerich 进行迁移(完整流程)
步骤 1️⃣:首次初始化(生成初始迁移)
aerich init-db- 作用:根据当前
models.py生成 第一个迁移文件(包含所有表的 CREATE 语句) - 生成文件示例:
migrations/models/0_20241214120000_init.py
💡 如果数据库已存在表,不要运行 init-db!应先让模型与数据库一致,再生成空迁移。步骤 2️⃣:修改模型(例如新增字段)
# models.py
class User(Model):
id = fields.IntField(pk=True)
username = fields.CharField(max_length=50, unique=True)
email = fields.CharField(max_length=255, null=True) # ← 新增字段步骤 3️⃣:生成迁移脚本
aerich migrate --name add_email_to_user- 自动检测模型变化
- 生成新迁移文件:
migrations/models/1_20241214120500_add_email_to_user.py - 内容示例:
from aerich import Command
async def upgrade():
await Command.upgrade("ALTER TABLE `user` ADD COLUMN `email` VARCHAR(255)")
async def downgrade():
await Command.downgrade("ALTER TABLE `user` DROP COLUMN `email`")✅ Aerich 会智能生成 SQL(针对不同数据库语法)
步骤 4️⃣:应用迁移(升级数据库)
aerich upgrade- 执行所有未应用的迁移(按时间顺序)
- 更新
aerich内部的迁移记录表(aerich_migrate)
步骤 5️⃣:回滚(可选)
aerich downgrade # 回滚最近一次迁移
aerich downgrade --n 2 # 回滚最近两次⚠️ 注意:不是所有操作都能完美回滚(如删除字段),需人工检查 downgrade() 函数📜 六、常用命令速查
| 命令 | 说明 |
|---|---|
aerich init -t config.TORTOISE_ORM | 初始化 Aerich |
aerich init-db | 生成初始迁移(仅首次) |
aerich migrate --name xxx | 根据模型变更生成新迁移 |
aerich upgrade | 应用所有未执行的迁移 |
aerich downgrade | 回滚最近一次迁移 |
aerich heads | 查看最新迁移版本 |
aerich history | 列出所有迁移历史 |
aerich show <migration_file> | 显示某次迁移的 SQL |
⚠️ 七、注意事项 & 最佳实践
1. 不要手动修改迁移文件
- 除非你知道自己在做什么(如修复 SQL 语法)
- 修改后务必测试
upgrade和downgrade
2. 生产环境禁止 generate_schemas=True
# FastAPI 注册时
register_tortoise(
app,
db_url=...,
modules={"models": [...]},
generate_schemas=False, # ← 必须设为 False!
)3. 团队协作:提交迁移文件到 Git
- 所有开发者共享
migrations/目录 - 避免多人同时改模型导致冲突
4. MySQL 注意字符集
- 确保数据库/表使用
utf8mb4 - 否则 emoji 或特殊字符会出错
5. SQLite 限制
- SQLite 不支持
DROP COLUMN(旧版本) - Aerich 会尝试重建表,但需谨慎
🧪 八、完整工作流示例(开发新功能)
# 1. 拉取最新代码
git pull
# 2. 应用他人写的迁移
aerich upgrade
# 3. 修改 models.py(比如加个字段)
# 4. 生成自己的迁移
aerich migrate --name add_avatar_url
# 5. 测试升级/回滚
aerich upgrade
aerich downgrade
# 6. 提交代码 + 迁移文件
git add models.py migrations/
git commit -m "feat: add avatar_url field"📊 九、Aerich vs Alembic 对比
| 特性 | Aerich | Alembic |
|---|---|---|
| ORM 支持 | Tortoise-ORM | SQLAlchemy |
| 异步支持 | ✅ 原生 | ✅(需 async wrapper) |
| 自动检测变更 | ✅ | ✅(需配置) |
| 回滚支持 | ✅(基础) | ✅(强大) |
| 社区成熟度 | 中等(较新) | ⭐⭐⭐⭐⭐(非常成熟) |
| 学习成本 | 低(Django 风格) | 中高 |
✅ 结论:如果你用 Tortoise-ORM,Aerich 是唯一官方推荐的迁移工具。
🆘 十、常见问题解决
❌ 报错:ModuleNotFoundError: No module named 'aerich.models'
→ 检查 TORTOISE_ORM 配置中的 models 列表是否包含 "aerich.models"
❌ 报错:Table 'aerich_migrate' doesn't exist
→ 运行 aerich init-db(仅首次)或 aerich upgrade 创建元数据表
❌ 迁移没检测到模型变化?
→ 确保:
- 模型文件在
TORTOISE_ORM["apps"]["models"]["models"]中 - 已保存文件
- 没有语法错误
✅ 总结
Aerich = Tortoise-ORM 的“安全网”
它让你可以:
- 安心修改模型
- 团队协作无冲突
- 生产环境平滑升级
只需记住四步:
aerich init -t config.TORTOISE_ORM
aerich init-db # 首次
aerich migrate --name xxx
aerich upgrade
评论已关闭