Django 迁移过程及常见操作

7 篇文章 0 订阅

在 Django 中,数据库迁移涉及三个部分

  • Models:只记录了现在的 Model 是什么样子的;
  • Migrations:记录了 Model 从创建开始到每一次的修改记录
  • django_migrations 表:migrations 迁移执行时会在该表中记录每一次操作,我们回退版本以及确认是否执行迁移都是通过这张表

1. 操纵 model 的流程和原理

正常的顺序是:修改模型 model -> 执行 makemigrations -> 执行 migrate

而在这一过程中,Django 做了哪些工作呢?如何将我们对 model 的操作映射到数据库的 DDL 变化中

类似 声明式 的方式,在 migrations 文件夹中,从 0001_xxx.py 开始到最后一个迁移文件最终 Django 知道了这个模型 Model-1 当前的状态,与现在我们修改过的 Model 对比就得到了 diff,而消除不同的结果就是生成一个新的 migrations 文件。

如果我们再次执行 migrations 命令,也并不会有新的迁移文件产生,因为此时 Django 最后得到的 Model 与当前的 Model 一致,这就是类似声明式的地方——声明式天生的幂等性

此时,在空白数据库上,我们可以执行 migrate 命令生成我们需要的表结构

在实际工作环境中,我们一般有一个生产环境和测试环境,测试环境通常迁移版本要高于生产环境,而 Django 如何知道该迁移哪些内容,就由生产环境中,数据库中的 django_migrations 表确认

这张图是给一个很简单的 User Model 增加了一个字段。注意一开始蓝色的 Model 和 Table 是 map 的,最终状态红色的 Model 和 Table 也是 map 的。

请添加图片描述

2. 常见操作

2.1 迁移需要回滚怎么办?

查看迁移记录
# 如果不加app名称则查看所有迁移记录
>>> python manage.py showmigrations my_app
my_app
 [X] 0001_initial
 [X] 0002_xxxxxxx
 [X] 0003_xxxxxxx

其中 [x] 表示已迁移

撤销最近迁移

如果我想撤销掉 0003 的迁移,只需要重新执行一遍 0002 的迁移文件

python manage.py migrate my_app 0002

此时,终端将提示将迁移回滚

回滚到某次

命令同上,回滚到某次就执行某次到迁移序号

撤销全部迁移
python manage.py migrate my_app zero

2.2 migration 文件太多太卡怎么办?

可以参考本站 《Django 合并清理 migrations 文件》 一文,搜索可见

注意 ⚠️ 备份!!!

注意 ⚠️ 备份!!!

注意 ⚠️ 备份!!!

2.3 migrate 执行到一半失败了怎么办?

可以参照 2.1 的回滚操作,先回滚到失败前的版本,然后确认自己是否是生成了正确的迁移文件,以及迁移是否符合数据库约束

2.4 migration 是否需要上传到 git 仓库?

需要,首先,可以使用版本控制,可以最大程度保证大家使用的同一套迁移文件,防止重新生成可能造成的表结构不一致(等同于删除所有迁移文件重新生成),可以参考案例

2.5 和同事同时生成了同一个版本号的迁移文件怎么办,如 0005_xxx.py

这个其实是最简单的情况,迁移时,Django 自身就会提示你输入这条命令

python manage.py makemigrations --merge

会自动生成一个新的迁移文件然后兼容这两个迁移,执行这句话后再重新执行 python manage.py migrate 就好

或者删除这两个文件,由一个人重新生成迁移

2.6 我什么 models 都没改,但是每次 make migrations 都会生成新的?

举个例子吧,我之前的 models 里面一个 default 值用了字典,我们知道字典 key 是没有顺序的(Python 3.7)之前,就导致每次 make migrations 的时候,顺序都有几率不一样,Django 就认为状态不一致,需要新的 migration 文件来消除 diff。

可能就是因为不经意的修改影响到 model,需要确认一下自己这次 coding 做什么了

2.7 查看 migrations 迁移文件对应的 SQL

$ python manage.py sqlmigrate users 0001
BEGIN;
--
-- Create model Users
--
CREATE TABLE "users_users" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(33) NOT NULL, "age" integer NOT NULL, "gender" varchar(8) NULL);
COMMIT;

推荐:Decoupling database migrations from server startup: why and how

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值