FastAPI系列(17):ORM的迁移命令
本系列汇总,请查看这里:https://www.cnblogs.com/uncleyong/p/19503695
aerich简介及安装
aerich 是 Tortoise ORM 官方配套的数据库迁移工具,类比 Django 中的 makemigrations 和 migrate 命令 —— 它能追踪你对 Tortoise 模型(数据库表结构)的修改(比如新增字段、修改字段类型、删除模型等),并生成对应的 SQL 迁移脚本,让你可以安全地升级 / 回滚数据库表结构,避免手动写 SQL 带来的错误和兼容性问题。
核心特性
- 自动生成迁移脚本(记录模型的增删改);
- 支持迁移脚本的执行(升级表结构)和回滚(恢复到之前的版本);
- 适配 Tortoise ORM 支持的所有数据库(SQLite/MySQL/PostgreSQL);
- 命令行操作,用法和 Django 的迁移命令高度相似,上手成本低。
(.venv) PS D:\qzcsbj\fast\test_orm> aerich -h Usage: aerich [OPTIONS] COMMAND [ARGS]... Options: -V, --version Show the version and exit. -c, --config TEXT Config file. [default: pyproject.toml] --app TEXT Tortoise-ORM app name. -h, --help Show this message and exit. Commands: downgrade Downgrade to specified version. fix-migrations Fix migration files to include models state for aerich... heads Show currently available heads (unapplied migrations). history List all migrations. init Initialize aerich config and create migrations folder. init-db Generate schema and generate app migration folder. init-migrations Generate app migration folder and your first migration. inspectdb Prints the current database tables to stdout as... migrate Generate a migration file for the current state of the... upgrade Upgrade to specified migration version.
翻译
downgrade —— 降级到指定版本 fix-migrations —— 修复迁移文件,使其包含 Aerich 所需的模型状态 heads —— 查看当前可用的迁移头(未应用的迁移) history —— 列出所有迁移记录 init —— 初始化 Aerich 配置并创建迁移文件夹 init-db —— 生成数据库表结构并创建应用的迁移文件夹 init-migrations —— 创建应用的迁移文件夹并生成初始迁移文件 inspectdb —— 将当前数据库中的数据表结构输出到标准输出 migrate —— 根据模型的当前状态生成迁移文件 upgrade —— 升级到指定的迁移版本
创建数据库
drop database if exists fast;
create database fast charset utf8;
show databases;
show create database fast;


- 打开设置(Ctrl+Alt+S 或 ⌘+,)→ Plugins → Marketplace,搜索 Database Navigator,安装后重启 PyCharm。
- 重启后,通过 View → Tool Windows → DB Browser 打开数据库管理界面。
- 点击 + 配置数据库连接,步骤同专业版,测试通过后即可使用。

连接数据库配置

TORTOISE_ORM = {
'connections': {
'default': {
'engine': 'tortoise.backends.mysql',
'credentials': {
'host': '12.26.0.9',
'port': '3306',
'user': 'root',
'password': 'mysql',
'database': 'fast',
'minsize': 1,
'maxsize': 5,
'charset': 'utf8mb4',
"echo": True
}
},
},
'apps': {
'models': {
'models': ['models', "aerich.models"],
'default_connection': 'default',
}
},
'use_tz': False,
'timezone': 'Asia/Shanghai'
}
迁移(含升级、降级)
进入test_orm目录:cd .\test_orm\
aerich init -t settings.TORTOISE_ORM # TORTOISE_ORM配置的位置在settings.py中

初始化完会在当前目录生成一个文件(pyproject.toml)和一个文件夹(migrations)
- pyproject.toml:保存配置文件路径
- migrations:存放迁移文件

pyproject.toml内容

此时数据库还没有表

- 1. 执行后,数据库中就有相应的表了
- 2. 如果`TORTOISE_ORM`配置文件中的`models`改了名(包含改了目录位置),则执行这条命令时需要增加`--app`参数来指定你修改的名字

迁移文件名的格式为 {version_num}_{datetime}_{name|update}.py,name默认值是update

init文件内容
from tortoise import BaseDBAsyncClient
RUN_IN_TRANSACTION = True
async def upgrade(db: BaseDBAsyncClient) -> str:
return """
CREATE TABLE IF NOT EXISTS `clas` (
`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL COMMENT '班级名称'
) CHARACTER SET utf8mb4;
CREATE TABLE IF NOT EXISTS `student` (
`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
`name` VARCHAR(32) NOT NULL COMMENT '姓名',
`pwd` VARCHAR(32) NOT NULL COMMENT '密码',
`sno` INT NOT NULL COMMENT '学号',
`clas_id` INT NOT NULL,
CONSTRAINT `fk_student_clas_4be9b492` FOREIGN KEY (`clas_id`) REFERENCES `clas` (`id`) ON DELETE CASCADE
) CHARACTER SET utf8mb4;
CREATE TABLE IF NOT EXISTS `teacher` (
`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL COMMENT '姓名',
`pwd` VARCHAR(32) NOT NULL COMMENT '密码',
`tno` INT NOT NULL COMMENT '老师编号'
) CHARACTER SET utf8mb4;
CREATE TABLE IF NOT EXISTS `course` (
`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(32) NOT NULL COMMENT '课程名称',
`teacher_id` INT NOT NULL COMMENT '课程讲师表',
CONSTRAINT `fk_course_teacher_2de38fe7` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`id`) ON DELETE CASCADE
) CHARACTER SET utf8mb4;
CREATE TABLE IF NOT EXISTS `aerich` (
`id` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`version` VARCHAR(255) NOT NULL,
`app` VARCHAR(100) NOT NULL,
`content` JSON NOT NULL
) CHARACTER SET utf8mb4;
CREATE TABLE IF NOT EXISTS `student_course` (
`student_id` INT NOT NULL,
`course_id` INT NOT NULL,
FOREIGN KEY (`student_id`) REFERENCES `student` (`id`) ON DELETE CASCADE,
FOREIGN KEY (`course_id`) REFERENCES `course` (`id`) ON DELETE CASCADE,
UNIQUE KEY `uidx_student_cou_student_0d222b` (`student_id`, `course_id`)
) CHARACTER SET utf8mb4 COMMENT='学生选课表';"""
async def downgrade(db: BaseDBAsyncClient) -> str:
return """
"""
查看表

pycharm插件连接上数据库

表信息
desc;
字段顺序和models文件中一致


show full columns from student_course;


命令格式:aerich migrate [--name] (标记修改操作)


如果没加标记,默认就是显示update
![]()
数据库表还没更新

文件内容:升级upgrade和降级downgrade
from tortoise import BaseDBAsyncClient
RUN_IN_TRANSACTION = True
async def upgrade(db: BaseDBAsyncClient) -> str:
return """
ALTER TABLE `course` ADD `addr` VARCHAR(32) NOT NULL COMMENT '教室' DEFAULT '';"""
async def downgrade(db: BaseDBAsyncClient) -> str:
return """
ALTER TABLE `course` DROP COLUMN `addr`;"""

此时数据库表就更新了


回滚了

此时迁移文件内容没变

我们在模型文件中注释掉addr这个字段
class Course(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=32, description="课程名称")
teacher = fields.ForeignKeyField("models.Teacher", related_name='courses', description='课程讲师表')
# addr = fields.CharField(max_length=32, description="教室", default="")
同时Clas新增desc字段
class Clas(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=32, description="班级名称")
desc = fields.CharField(max_length=32, default="")
执行:aerich migrate --name add_column_desc_to_Clas


文件名和内容都改了
from tortoise import BaseDBAsyncClient
RUN_IN_TRANSACTION = True
async def upgrade(db: BaseDBAsyncClient) -> str:
return """
ALTER TABLE `clas` ADD `desc` VARCHAR(32) NOT NULL DEFAULT '';"""
async def downgrade(db: BaseDBAsyncClient) -> str:
return """
ALTER TABLE `clas` DROP COLUMN `desc`;"""
aerich upgrade



给描述加上值,也就是给表中desc字段的Comment加上值
class Clas(Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=32, description="班级名称")
desc = fields.CharField(max_length=32, description="班级描述", default="")
执行:aerich migrate --name add_column_desc_description_to_Clas

from tortoise import BaseDBAsyncClient
RUN_IN_TRANSACTION = True
async def upgrade(db: BaseDBAsyncClient) -> str:
return """
ALTER TABLE `clas` MODIFY COLUMN `desc` VARCHAR(32) NOT NULL COMMENT '班级描述' DEFAULT '';"""
async def downgrade(db: BaseDBAsyncClient) -> str:
return """
ALTER TABLE `clas` MODIFY COLUMN `desc` VARCHAR(32) NOT NULL DEFAULT '';"""
aerich upgrade



aerich 不支持直接回滚到指定的历史版本,必须顺序回滚,也就是说只能从最新的迁移开始逐个回滚
aerich downgrade






执行升级,会执行所有


执行降级,会一个一个执行


__EOF__
关于博主:擅长性能、全链路、自动化、企业级自动化持续集成(DevTestOps)、测开等
面试必备:项目实战(性能、自动化)、简历笔试,https://www.cnblogs.com/uncleyong/p/15777706.html
测试提升:从测试小白到高级测试修炼之路,https://www.cnblogs.com/uncleyong/p/10530261.html
欢迎分享:如果您觉得文章对您有帮助,欢迎转载、分享,也可以点击文章右下角【推荐】一下!

浙公网安备 33010602011771号