重新运行 Django 数据迁移
Rerun a Django data migration
如何在 Django 1.8+ 上重新运行数据迁移?如果相关,我的迁移编号为 0011_my_data_migration.py,并且是最新的迁移。
假回迁移到你想重新迁移的那个之前运行。
./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:
This is intended for advanced users to manipulate the current migration state directly if they’re manually applying changes; be warned that using --fake
runs the risk of putting the migration state table into a state where manual recovery will be needed to make migrations run correctly.
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
根据已接受的答案,这里有一个用于重新应用给定迁移的脚本。
#! /bin/bash
# This script re-applies a given migration.
app_name=""
migration_index=""
prev_migration_index="$(echo "$migration_index" | sed 's/^0*//' | awk '{ print - 1 }' | xargs printf "%04d")"
last_migration_index="$(django-admin showmigrations --plan | grep -oP "\.\K\d{4}" | 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>
如何在 Django 1.8+ 上重新运行数据迁移?如果相关,我的迁移编号为 0011_my_data_migration.py,并且是最新的迁移。
假回迁移到你想重新迁移的那个之前运行。
./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:
This is intended for advanced users to manipulate the current migration state directly if they’re manually applying changes; be warned that using
--fake
runs the risk of putting the migration state table into a state where manual recovery will be needed to make migrations run correctly.
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
根据已接受的答案,这里有一个用于重新应用给定迁移的脚本。
#! /bin/bash
# This script re-applies a given migration.
app_name=""
migration_index=""
prev_migration_index="$(echo "$migration_index" | sed 's/^0*//' | awk '{ print - 1 }' | xargs printf "%04d")"
last_migration_index="$(django-admin showmigrations --plan | grep -oP "\.\K\d{4}" | 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>