惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google Online Security Blog
Google Online Security Blog
博客园_首页
酷 壳 – CoolShell
酷 壳 – CoolShell
Jina AI
Jina AI
博客园 - Franky
大猫的无限游戏
大猫的无限游戏
Hugging Face - Blog
Hugging Face - Blog
博客园 - 司徒正美
V
V2EX
雷峰网
雷峰网
云风的 BLOG
云风的 BLOG
V
Visual Studio Blog
F
Full Disclosure
Y
Y Combinator Blog
V
V2EX - 技术
Attack and Defense Labs
Attack and Defense Labs
S
Security @ Cisco Blogs
Schneier on Security
Schneier on Security
Microsoft Azure Blog
Microsoft Azure Blog
SecWiki News
SecWiki News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The GitHub Blog
The GitHub Blog
量子位
PCI Perspectives
PCI Perspectives
S
Secure Thoughts
D
Darknet – Hacking Tools, Hacker News & Cyber Security
AWS News Blog
AWS News Blog
Blog — PlanetScale
Blog — PlanetScale
爱范儿
爱范儿
K
Kaspersky official blog
B
Blog
A
Arctic Wolf
Hacker News: Ask HN
Hacker News: Ask HN
L
LangChain Blog
T
Tor Project blog
P
Privacy & Cybersecurity Law Blog
Recent Announcements
Recent Announcements
宝玉的分享
宝玉的分享
The Register - Security
The Register - Security
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
L
Lohrmann on Cybersecurity
D
Docker
A
About on SuperTechFans
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Google DeepMind News
Google DeepMind News
The Last Watchdog
The Last Watchdog
S
Security Affairs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Privacy International News Feed
Simon Willison's Weblog
Simon Willison's Weblog

博客园 - 全栈测试笔记

博文阅读密码验证 - 博客园 FastAPI系列(24):ORM操作之删除接口开发 单例模式管理模型客户端的几种实现方式 博文阅读密码验证 - 博客园 FastAPI系列(23):ORM操作之编辑接口开发 FastAPI系列(22):ORM之多对多查询记录 FastAPI系列(21):ORM之多对多添加记录 CC Switch配置模型 Claude Code安装 FastAPI系列(20):ORM添加表记录 FastAPI系列(19):ORM响应页面数据 博文阅读密码验证 - 博客园 FastAPI系列(18):ORM查询操作 FastAPI系列(16):ORM创建模型类 FastAPI系列(15):Jinja2模板语法之控制结构 FastAPI系列(14):Jinja2模板语法之过滤器 FastAPI系列(13):Jinja2模板介绍、模板语法之变量渲染 FastAPI系列(12):响应模型参数 【汇总】FastAPI系列教程
FastAPI系列(17):ORM的迁移命令
全栈测试笔记 · 2026-01-29 · via 博客园 - 全栈测试笔记

本系列汇总,请查看这里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】