重新运行 Django 数据迁移

Posted

技术标签:

【中文标题】重新运行 Django 数据迁移【英文标题】:Rerun a Django data migration 【发布时间】:2015-11-04 09:01:42 【问题描述】:

如何在 Django 1.8+ 上重新运行数据迁移?如果相关,我的迁移编号为 0011_my_data_migration.py,是最新的迁移。

【问题讨论】:

请注意,Q 和解决方案仍在 Django 2.1 上运行 【参考方案1】:

根据接受的答案,这是重新应用给定迁移的脚本。

#! /bin/bash
# This script re-applies a given migration.
app_name="$1"
migration_index="$2"

prev_migration_index="$(echo "$migration_index" | sed 's/^0*//' | awk ' print $1 - 1 ' | xargs printf "%04d")"
last_migration_index="$(django-admin showmigrations --plan | grep -oP "\.\K\d4" | sort | tail -n 1)"

# fake-migrate to the migration prior to the one we want to reapply
django-admin migrate --fake "$app_name" "$prev_migration_index"
# reapply the migration
django-admin migrate "$app_name" "$migration_index"
# fake-migrate to the last migration
django-admin migrate --fake "$app_name" "$last_migration_index"

用法:

$ bash reapply_migration.sh <app_name> <migration_to_reapply_index>

【讨论】:

【参考方案2】:

Alasdair 的回答对此给出了免责声明,但只有在您的迁移是幂等的情况下,伪造迁移回前一个迁移才是安全的,这意味着您可以多次运行它而不会产生重复数据等副作用。大多数人不会以这种方式编写迁移,但这是一种很好的做法。

您有两个选项可以确保此过程安全:

    使您的数据迁移具有幂等性。这意味着任何创建的数据要么被重复使用(如Model.objects.get_or_create() 方法),要么被删除并重新创建。重用是更好的选择,因为删除和重新创建会更改数据库索引和序列。 进行反向数据迁移。您可以通过将 2 个函数传递给 migrations.RunPython() 来做到这一点。例如,如果您有 migrations.RunPython(add_countries),您可以将其更改为 migrations.RunPython(add_countries, remove_countries),并在第二个函数中删除所有相关国家/地区。

如果您选择选项 #2,那么您将运行:

./manage.py migrate yourapp 0010_my_previous_data_migration
./manage.py migrate yourapp 0011_my_data_migration

如果你想把它做成一个衬里,这样你就可以反复使用它:

./manage.py migrate yourapp 0010_my_previous_data_migration && ./manage.py migrate yourapp 0011_my_data_migration

【讨论】:

你应该在单行中使用--fake 吗? 不,这是来自 OP 的复制和粘贴错误。固定。【参考方案3】:

在您要重新运行的迁移之前伪造回迁移。

./manage.py migrate --fake yourapp 0010_my_previous_data_migration

然后重新运行迁移。

./manage.py migrate yourapp 0011_my_data_migration

然后,您可以伪造回您已运行的最新迁移。在你的情况下,你说 0011 是最新的,所以你可以跳过这个阶段。

./manage.py migrate --fake yourapp 0014_my_latest_data_migration

请注意,根据数据库的状态和迁移的内容,像这样重新运行迁移可能会导致错误。请注意关于 --fake 选项的警告 in the docs:

这是供高级用户在手动应用更改时直接操作当前迁移状态的;请注意,使用--fake 存在将迁移状态表置于需要手动恢复以使迁移正确运行的状态的风险。

【讨论】:

./manage.py migrate --fake yourapp zero 如果是第一次迁移。 如果你需要真正找到之前的迁移,另一个有用的命令是./manage.py showmigrations

以上是关于重新运行 Django 数据迁移的主要内容,如果未能解决你的问题,请参考以下文章

Django 1.7 迁移挂起

django数据库的表已迁移的不能重新迁移的解决办法

django迁移地狱,丢了一张桌子。试图找回它

django:删除表后怎么重新数据迁移生成表

django迁移过后没有数据库

石墨烯代码在 Django 数据迁移之前运行