HOWTO · Django
在 Django 中重置迁移
了解如何在 Django 中重置迁移
本页内容
Django 迁移是用于更改数据库架构的版本化指令。Django 也会在数据库中记录已应用的迁移。因此,“重置迁移”可能指几种不同操作:将某个应用回退到已知迁移、撤销该应用的迁移、保留架构但清空数据行,或替换开发数据库。应根据所需结果选择操作;删除迁移文件不能替代其中任何一种操作。
执行破坏性操作前,请确认命令将使用哪个设置文件和数据库,使用 python manage.py showmigrations 检查当前迁移状态,并在数据需要保留时制作可恢复的备份。下文命令中的 AppName 是应用标签的占位符,例如 blog;请使用 Django 识别的标签,它不一定与 Python 包的完整路径相同。
重置迁移会改变什么
迁移文件描述架构操作,也可能会移动或转换数据。迁移表记录已应用的迁移名称。将某个应用回退时,Django 会在有可用反向操作的情况下执行这些操作,从而改变记录的架构状态;迁移文件本身不会被改写。使用 flush 清空数据行会保留架构和迁移历史。替换开发数据库则会删除其中的数据和迁移记录,之后必须重新应用迁移。
这些操作影响的范围各不相同。如果要撤销近期的架构更改,应指定更早的迁移。如果某个应用不应有任何已应用的迁移,应将目标设为 zero。如果只想清空应用数据,应使用 flush。如果本地数据库可以丢弃,并且需要从头重建,应替换该数据库,再次迁移项目。不要为了让数据库看起来像已重置就删除迁移文件:现有环境和团队成员仍依赖这些文件所定义的共享迁移历史。
将一个应用回退到更早的迁移
使用 showmigrations AppName 查找目标迁移,或查看该应用的迁移文件。然后运行 python manage.py migrate AppName 0004,将该应用回退到迁移 0004;请将两个占位值都替换为实际的应用标签和目标迁移。如果迁移列表中显示的名称是 initial 之类的名称,也可以用它代替编号。
目标是应用该迁移后的状态,因此该应用之后的迁移都会被反向执行。反向操作可能会更改或删除列,也可能删除其中存储的数据。为保持迁移图一致,Django 还可能需要调整依赖于该应用的迁移。运行命令前,请检查计划中的更改,以及当前设置所选中的数据库;其他应用依赖目标应用时尤其要谨慎。
在根据项目情况调整命令之前,可以先用一段简短的 Python 代码明确命令模板。请将示例中的应用和目标替换为迁移列表中的实际值。
运行此示例:
本节中的代码以及显示的标签或输出仍为英文。
app_label = "blog"
target_migration = "0004"
print(f"python manage.py migrate {app_label} {target_migration}")
python manage.py migrate blog 0004
这段代码会打印命令模板;它不会连接 Django,也不会更改数据库。
将一个应用重置到零
若要撤销某个应用的全部迁移,请使用 python manage.py migrate AppName zero。此操作影响该应用的迁移状态,并反向执行其架构操作;它不是整个数据库范围的重置。根据涉及的迁移和关系,反向操作可能会删除表或数据,也可能需要同时撤销依赖迁移。如果结果不确定,请先在可丢弃的环境中检查预期影响。
在共享或已部署的项目中,不要在此操作后删除该应用的迁移文件。Django 依靠这些文件,在其他数据库上构建架构。如果团队确实要压缩或替换迁移历史,应在所有环境中协调一套单独的迁移维护流程,而不能把 zero 当成删除这段历史的许可。
重置开发数据库
如果要清空数据库数据,同时保留表和已应用的迁移,请运行 python manage.py flush。该命令会删除数据库中的数据并重置序列,但会保留架构和迁移记录。若要重新加载 fixture 或清空应用数据,这通常是合适的选择;它不会根据迁移文件重建架构。
如果要在本地彻底重建数据库,请先停止正在使用该数据库的进程,确认当前设置指向可丢弃的开发数据库,再按所用数据库引擎的流程替换数据库。使用 SQLite 时,可以删除本地数据库文件;使用服务器数据库时,通常需要凭适当凭据删除并重新创建开发数据库。然后运行 python manage.py migrate 来创建架构并应用项目迁移。不同数据库引擎的删除命令各不相同,请遵循对应数据库的文档流程;没有明确的恢复方案时,切勿将开发环境的重置命令照搬到生产环境。
删除迁移文件并根据当前模型创建新迁移,属于需要协调的独立历史重写。即使本地数据库已成功重建,这种做法仍可能破坏已部署的安装、团队成员的工作副本和迁移依赖关系。请将迁移文件纳入版本控制;日常模型更改应使用新的迁移。
安全处理不可逆迁移
有些迁移无法反向执行,因为其中的操作会丢弃信息,或者没有定义反向操作。Django 可能会以 IrreversibleError 中止回滚。失败后数据库处于什么状态,取决于迁移是否具有原子性以及数据库的事务行为;回滚可能已经产生部分影响。不要假设回滚命令能够恢复已删除或转换的数据。
尝试回滚前,请检查迁移操作,并备份必须保留的数据。先在近期数据库副本上测试回滚,确认生成的架构和重要记录,再在实际执行前重新确认目标环境。如果迁移不可逆,请从合适的备份恢复,或编写有意设计的前向迁移来达到所需状态;不要手动删除迁移记录来掩盖不一致。