Django4 中文入门教程 Django4.0 迁移-压缩迁移

2024-02-25 开发教程 Django4 中文入门教程 匿名 4

我们鼓励你自由地进行迁移,而不要担心你有多少迁移;迁移代码经过优化,可以一次处理几百个迁移,而不会有太多的减速。然而,最终你会希望从几百个迁移回归到只有几个,这就是压缩的作用。

压缩是将一组现有的多个迁移减少到一个(有时是几个)迁移,这些迁移仍然代表相同的更改。

Django通过获取所有现有迁移,提取它们的 ​Operation ​并将它们按顺序排列,然后对它们运行一个优化器,以尝试减少列表的长度——例如,它知道 ​CreateModel ​和 ​DeleteModel ​相互抵消,它还知道 ​AddField ​可以卷入 ​CreateModel​。

一旦操作序列被尽可能地减少——可能的数量取决于你的模型有多紧密交织,如果你有任何 RunSQL 或 RunPython 操作(除非它们被标记为 ​elidable​,否则无法被优化),Django就会把它写回一组新的迁移文件中。

这些文件被标记为替换了先前压缩的迁移,因此它们可以与旧迁移文件共存,Django 将根据你在历史记录中的位置智能地在它们之间切换。如果你仍处于压缩过程中,则它将继续使用它们直到结束,然后切换到压缩历史记录,而新安装将使用新压缩后的迁移并跳过所有旧迁移。

这样你就可以压缩而不至于把目前还没有完全更新的生产系统搞乱。推荐的流程是压缩,保留旧文件,提交并发布,等到所有系统都升级到新版本(或者如果你是第三方项目,确保你的用户按顺序升级版本,不跳过任何一个版本),然后删除旧文件,提交并进行第二次发布。

支持这一切的命令是 ​squashmigrations​——把你想压缩的应用标签和迁移名称传给它,它就会开始工作:

$ ./manage.py squashmigrations myapp 0004
Will squash the following migrations:
- 0001_initial
- 0002_some_change
- 0003_another_change
- 0004_undo_something
Do you wish to proceed? [yN] y
Optimizing...
Optimized from 12 operations to 7 operations.
Created new squashed migration /home/andrew/Programs/DjangoTest/test/migrations/0001_squashed_0004_undo_something.py
You should commit this migration but leave the old ones in place;
the new migration will be used for new installs. Once you are sure
all instances of the codebase have applied the migrations you squashed,
you can delete them.

如果要设置压缩迁移的名称而不是使用自动生成的迁移名称,请使用 ​squashmigrations --squashed-name​ 选项。
请注意,Django 中的模型相互依赖可能会变得非常复杂,压缩可能会导致迁移无法运行;要么是优化错误(在这种情况下,你可以用 ​--no-optimize​ 再试一次,不过你也应该报告这个问题),要么是 ​CircularDependencyError​,在这种情况下,你可以手动解决它。
要手动解决 ​CircularDependencyError ​问题,请将循环依赖中的外键分离到单独的迁移中,并将依赖项移到另一个应用上。如果你不确定,请参见 ​makemigrations ​在被要求从模型创建全新的迁移时如何处理问题。在未来的 Django 版本中,​squashmigrations ​将被更新以尝试自己解决这些错误。
一旦你压缩了你的迁移,你应该把它和它所替代的迁移一起提交,并把这个更改分发到你的应用程序的所有运行中的实例,确保它们运行 ​migrate ​来将更改存储在它们的数据库中。
然后,你必须通过以下方法将压缩的迁移过渡到正常迁移:

  • 删除它替换的所有迁移文件。
  • 将所有依赖被删除迁移的迁移更新为依赖被压缩的迁移。
  • 删除压缩迁移的 ​Migration ​类的 ​replaces ​属性(这就是 Django 告诉它是压缩迁移的方式)。

压缩迁移后,在完全将其转换为正常迁移之前,你不应该再重新压缩该压缩的迁移。