如何压缩最近的 Django 迁移?

How to squash recent Django migrations?

在 Django 的迁移代码中,有一个 squashmigrations 命令:"Squashes the migrations for app_label up to and including migration_name down into fewer migrations, if possible."

因此,如果您想压缩前 5 次迁移,这会有所帮助。

从特定 migration_name 开始压缩的最佳方法是什么?

在我目前正在进行的项目中,我们添加了 5-10 个新的迁移文件,因为我们添加了新功能。我们将立即部署整个项目,看起来 运行 单独部署这些项目会花费太长时间。我想将这个项目的所有迁移压缩到一个迁移中,并测试 运行 的时间。

您可以只删除迁移文件,然后再次运行 makemigrations。如果你有一个使用这些的开发部署,你应该 migrate back 到你删除的第一个之前的那个。

此外,最好先提交代码,以防出现问题。

另外:

The slight complication with this is that if there's custom RunPython code, it won't be included in the new migration created by makemigrations

python manage.py squashmigrations <appname> <squashfrom> <squashto>

python manage.py help squashmigrations

https://docs.djangoproject.com/en/dev/topics/migrations/#migration-squashing

这将使您能够更精细地控制要压缩的迁移,并让您保持更清晰的提交历史记录。删除 + 重新创建所有迁移可能会导致其他问题,例如循环依赖,具体取决于模型的构建方式。

我创建 django-squash https://pypi.org/project/django-squash/ 是为了不必在每个应用程序级别或更糟糕的是每个应用程序特定的迁移级别上处理迁移,并在每个项目级别。这个想法是希望在某个时候将它集成到核心 Django 中。

基本思路:

  • 你有一个产品,没有其他人增强的开源产品,但是你的,你的团队,你处理它。
  • 每次发布后,您都希望压缩在上一个版本中执行的所有迁移并开始新的迁移,因为您的产品已经从上一个版本和您的数据模型发展而来。
  • 你压扁,它会看看你之前是否压扁过,如果有,它会删除任何在你的代码库中不再有业务的非常旧的迁移。最后,创建一个新的迁移快照,并保留您周围的迁移。
  • 如果您觉得测试花费的时间太长,您将每隔 release/when 执行此操作 运行所有迁移。

示例:

/app1/migrations/__init__.py
/app1/migrations/0001_initial.py
/app1/migrations/0002_created_user_model.py
/app1/migrations/0003_added_username.py
/app1/migrations/0004_added_password.py
/app1/migrations/0005_last_name.py

您已全部应用。

但是每次您 运行 测试时,这些步骤中的每一个都需要 运行,占用宝贵的时间。所以我们压扁。新目录将如下所示:

/app1/migrations/__init__.py
/app1/migrations/0001_initial.py
/app1/migrations/0002_created_user_model.py
/app1/migrations/0003_added_username.py
/app1/migrations/0004_added_password.py
/app1/migrations/0005_last_name.py
/app1/migrations/0006_squash.py

0006_squash.py 中,您会发现一个 replaces = [..],其中包含迁移 1-5 的名称。如果您删除所有迁移并使用 elidable=False 执行 ./manage.py makemigrations + 任何 RunSQL/RunPython,您还会发现 Migration.operations = [..] 包含您期望的所有内容。如果您部署到缺少任何迁移 1-5 的环境,它将从源代码应用它,而不使用 0006。 (这是标准的 Django 迁移)

一段时间过去了,现在您的迁移看起来像这样:

/app1/migrations/__init__.py
/app1/migrations/0001_initial.py
/app1/migrations/0002_created_user_model.py
/app1/migrations/0003_added_username.py
/app1/migrations/0004_added_password.py
/app1/migrations/0005_last_name.py
/app1/migrations/0006_squash.py
/app1/migrations/0007_change_username_to_100_char.py
/app1/migrations/0008_added_dob.py

你又压扁了。这次将发生以下情况。 replaces = [..] 中的任何内容都将被删除。 0006_squash.py 将被修改为 replaces 是一个空列表。最后,将使用新的更改重新创建壁球。总而言之,将如下所示:

/app1/migrations/0006_squash.py
/app1/migrations/0007_change_username_to_100_char.py
/app1/migrations/0008_added_dob.py
/app1/migrations/0009_squash.py

再次开始循环。

Squash 迁移 命令在 Django 1.9 中引入

如果您正在使用 Django 1.8,您需要