方向不对,努力白费,经验类测试技术才是职场重要保险! | (点击→)【提醒】AI赋能的前提是对常规测试技术非常的熟悉,联系作者vx了解

FastAPI系列(17):ORM的迁移命令

 

本系列汇总,请查看这里https://www.cnblogs.com/uncleyong/p/19503695

 

aerich简介及安装

aerich 是 Tortoise ORM 官方配套的数据库迁移工具,类比 Django 中的 makemigrations 和 migrate 命令 —— 它能追踪你对 Tortoise 模型(数据库表结构)的修改(比如新增字段、修改字段类型、删除模型等),并生成对应的 SQL 迁移脚本,让你可以安全地升级 / 回滚数据库表结构,避免手动写 SQL 带来的错误和兼容性问题。

简单来说,aerich 解决了异步场景下 Tortoise ORM 的表结构版本管理问题,是生产环境中使用 Tortoise ORM 必不可少的工具。

核心特性

  • 自动生成迁移脚本(记录模型的增删改);
  • 支持迁移脚本的执行(升级表结构)和回滚(恢复到之前的版本);
  • 适配 Tortoise ORM 支持的所有数据库(SQLite/MySQL/PostgreSQL);
  • 命令行操作,用法和 Django 的迁移命令高度相似,上手成本低。
 
安装aerich:pip install aerich
 
常用命令:aerich -h
(.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;

image

image

 

另外,pycharm社区版无内置 Database 工具,需安装第三方插件:
  • 打开设置(Ctrl+Alt+S 或 ⌘+,)→ Plugins → Marketplace,搜索 Database Navigator,安装后重启 PyCharm。
  • 重启后,通过 View → Tool Windows → DB Browser 打开数据库管理界面。
  • 点击 + 配置数据库连接,步骤同专业版,测试通过后即可使用。

image

 

连接数据库配置

放到settings.py中

image

 

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中

image

 

初始化完会在当前目录生成一个文件(pyproject.toml)和一个文件夹(migrations)

  • pyproject.toml:保存配置文件路径
  • migrations:存放迁移文件
 

image

pyproject.toml内容

image

 

此时数据库还没有表

image

 

初始化数据库,一般情况下只用一次

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

image

 

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

image

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 """
        """

  

 查看表

image

 

pycharm插件连接上数据库

image

 

表信息

desc;

字段顺序和models文件中一致

image

 

image

 

show full columns from student_course;

image

image

 

更新模型并进行迁移

课程表加一个字段:addr = fields.CharField(max_length=32, description="教室", default="")
default表示加一个默认值,因为可能已经有记录了,有记录的这个字段就为空

 

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

执行:aerich migrate --name add_column_addr_to_Course
只是创建了file

image

 

image

如果没加标记,默认就是显示update

image

数据库表还没更新

image

 

文件内容:升级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`;"""

 

执行升级:aerich upgrade

image

 

此时数据库表就更新了

image

 

执行降级(回滚到上一个版本):aerich downgrade

image

回滚了

image

此时迁移文件内容没变

image

 

我们在模型文件中注释掉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

image

 

image

 

文件名和内容都改了

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

image

 

image

 

image

 

给描述加上值,也就是给表中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

image

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

image

 

image

 

image

 

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

aerich downgrade

image

 

image

 

image

 

image

 

image

 

image

 

执行升级,会执行所有

image

 

image

 

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

image

  

查看历史迁移记录

aerich history

image

 

【bak】

 

posted @ 2026-01-29 20:45  全栈测试笔记  阅读(2)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end