Django之 migration 原理

1.迁移解决的问题

  • 不用手动写 sql 去维护数据库
  • 不用手动创建数据库表,而是用 orm 编写 django 模型,里面的一个属性就是对应其数据库表中的一列
  • 确保模型定义和数据库架构同步(如果多人使用同一个数据库时,每个人的操作我们可能是不知道的,并且需要跟踪,这是很麻烦的,使用django迁移会很轻松的跟踪到每个修改的状态)
  • 算是缺点吧,不能使用sql 额外的去修改表结构,会损坏模型定义与当前数据库模式,这是不允许的。
    可能会报错:django.db.utils.InternalError: (1054, “Unknown column ‘title’ in ‘app01_titlegraph’”)

2.migrate 的作用

  • 负责应用迁移和撤销迁移
  • 迁移可以看做是数据库表结构的版本控制系统(会升序生成很多00$_auto_xx.py文件,文件名称根据修改内容会有所不同)
  • 因为唯一能确保数据库正确的方法是完整的记录修改历史
  • 执行迁移文件,使数据库架构与模型定义同步的操作列表
  • django_migration 表中生成一条迁移记录

3.什么情况下会生成 migration

  • 当执行 makemigrations 时模型将被扫描并与当前包含在你的迁移文件中的版本进行比较,然后将写出一组新的迁移
  • 将模型生成迁移脚本,负责将模型修改打包进独立的迁移文件中

4.migration 名称生成规则

  • 可以通过 --name 指定迁移文件的名称,如不指定,第一个迁移文件的名称默认为 001_initial
  • 迁移文件的名称基于当前时间,如果您继续使用系统,则名称将不同。
  • 如创建 model 的操作,migration 名称一般为 00x_{model名},如修改字段migration 名称一般为
    00x_date_timestmp

5.migration 文件中的内容

  • dependencies(list): 依赖,表示次迁移文件依赖的父级(列表包含可以应用此迁移之前必须应用的所有迁移)
    内容为一个元祖,第一个为app 的名字,第二个为此迁移必须应用的迁移
    注:第一次迁移列表中是没有内容的

  • operations(list):操作(CreateModel、DeleteModel、RenameModel、AlterModel、AddField
    等)

6.如何 migration 不会重复被应用到数据库

  • 如重复执行 migrate 会提示:No migrations to apply,对于每个应用的迁移,django 会在数据库表中
    django_migrations 插入一个新行,因此不会尝试重新运行它们
  • 如手动更改以应用的迁移文件,只要数据库中已经有相应的条目,django也会忽略这些更改,你可以从表中删除相应的但这并不是一个好主意

7.django 如何检测模型的更改

当你已经知道 migrate 里面的依赖关系以及 operations 里面的内容,但是如何确切的知道应该将那些内容放到这个 migrate 文件中来?你可能会说将模型与数据库模式做比较,但事实并非如此,在运行 makemigrations 时,django不会检查你的数据库,他不会将你的模型文件与早期版本进行比较,相反,Django会经历所有已应用的迁移,并建立模型外观的项目状态。然后将该项目状态与您当前的模型定义进行比较,并创建一个操作列表,当应用这些操作时,将使项目状态与模型定义保持最新。
附官网解释
operations 是关键;它们是一组声明性指令,它们告诉 Django 需要对哪些架构变更。Django 扫描它们并构建所有应用的所有架构变更的内存表示形式,然后使用它生成进行架构变更的 SQL。
该内存结构还用于确定模型与迁移当前状态之间的差异;Django 按顺序在内存中的模型集上运行所有的变更,得出你上次运行 makemigrations时模型的状态。然后,它使用这些模型与你的models.py 文件中的模型进行比较,以计算出你改变了什么。

8.取消应用迁移

幸运的是迁移不必走单向路,在很多情况下我们可以通过撤销迁移来达到数据库的状态。

  • 意识到所做的更改是一个坏主意
  • 如:想测试一位同事写的迁移
  • 取消迁移不会删除迁移文件,下次运行migrate时会再次迁移
  • 执行命令:migrate app_name {文件名}

9.多人协作问题

由于迁移存储在版本控制中,因此你有时会遇到这样的情况:
你和另一个开发人员都同时向同一应用提交了迁移,从而导致两次迁移的编号相同。
别担心——这些数字只是给开发者参考的,Django 只在乎每个迁移都有不同的名称。 迁移在文件中指定了它们所依赖的其他 哪些迁移——包括同一应用中的早期迁移,所以可以检测到同一应用有两个新的迁移没有排序。当这种情况发生时,Django 会提示你,并给你一些选项。如果它认为足够安全,它将为你自动线性化两个迁移。如果不安全,你就得自己去修改迁移
在这里插入图片描述
如图所示:A 分支和 B 分支基于 master 开发,同时生成了一个 002_auto_xx.py 文件,如果一方先被合掉并被应用到数据库,那么另一方被合并时会冲突。

附测试环境挂掉的日志(仅供参考)

django.db.utils.ProgrammingError: relation “xxx_user” already exists

报错流程解析:
在这里插入图片描述
原因分析:
开发人员1和开发人员2基于 master 分支开发,迁移文件已经到 003_auto_00 这个版本,这个时候开发人员1提交一个 004_auto_xx migration 上去并被合并,开发人员2将代码更新到最新版本,也就是基于 004_auto_xx 开发,这个时候开发人员2将 master 上面的 004_auto_xx 删除,重新生成一个 004_auto_xx migration 并提交 在执行 migrate 时提示:django.db.utils.ProgrammingError: relation “xxx_user” already exists 意思是:xxx_user 这张表已经存在,当开发人员1提交并合并后已经执行过 migrate,这个时候数据库已经生成了 xxx_user 这张表,开发人员2将 master 上面的 004_auto_xx 删掉并重新生成的这份 migration 文件中也包含了创建 xxx_user 这张表,导致重复创建。

猜你喜欢

转载自blog.csdn.net/qq_39253370/article/details/110185477