我已经使用 Django 大约 2 年了,并且有一个我一直害怕使用的功能:伪造迁移。
我几乎到处都看过,我能获得的最多信息来自 documentation,其中指出:
- 伪造的
告诉 Django 将迁移标记为已应用或未应用,但无需实际运行 SQL 来更改数据库模式。这是为了让高级用户在手动应用更改时直接操纵当前的迁移状态;请注意,使用 --fake 存在将迁移状态表置于需要手动恢复以使迁移正确运行的状态的风险。
--假初始
如果具有由该迁移中的所有 CreateModel 操作创建的所有模型的名称的所有数据库表已经存在,则允许 Django 跳过应用程序的初始迁移。此选项适用于首次对已使用迁移的数据库运行迁移时使用。但是,此选项不会检查匹配表名之外的匹配数据库模式,因此只有在您确信现有模式与初始迁移中记录的内容匹配时才能安全使用。
我大致了解了为什么要使用此功能。但是,我不明白它说这仅适用于高级用户的部分。
有人可以解释幕后发生的事情以及为什么需要手动恢复。
笔记
我不是在寻找伪造迁移时运行的确切原始 SQL 查询。我只是在寻找幕后发生的事情的一般概念,也许是一个示例,说明为什么伪造迁移会导致 makemigrations
无法正常工作的状态。
--fake
时,是否将迁移标记为已应用,在 django_migrations
表中定义,Django 使用迁移文件的 name
跟踪应用程序的所有已应用迁移以及何时应用。我花了一段时间才弄清楚这一点,因为文档并不清楚我在这里介绍的这个细节。
如果您需要将具有相似模型的两个分支组合或在它们之间切换,则它与类似于源代码 (git) 中的合并冲突的数据库问题有关。没有人故意喜欢它。
想象一下,您上周开始修改应用程序,可能是因为您发现了一个错误,或者您通过字段或表格扩展了应用程序。今天您收到了更新,但遇到了问题,因为有一个迁移添加了一个仍在您的数据库中的字段,您只能应用该迁移的其他部分。您可以通过运行查看迁移的 SQL 内容
./manage sqlmigrate some_app 0007_new_migration >customized-some_app-0007_new_migration.sql
将内容与上周所做的更改进行比较,并删除或注释掉仍然应用且不能重复的命令。手动运行所有剩余的 SQL。标记该迁移,就像它会自动应用一样:
./manage migrate --fake some_app 0007_new_migration
如果您破坏了某些东西,可能没有人可以帮助您,因为迁移系统不会更多地了解数据库的当前状态。因此,做备份、写笔记、使用沙箱并精确工作。
编辑:迁移表 django_migrations
是应用于所有应用的迁移的简单列表。此表中的行应始终与数据库结构处于同步状态。可以通过普通的 migrate
应用迁移。 (或通过反向迁移到较旧状态而未应用,当然通常会丢失一些数据)虚假迁移仅将更改应用于 django_migrations 表。
me => select * from django_migrations;
id | app | name | applied
----+----------+-------------------------+-------------------------------
1 | some_app | 0001_initial | 2017-10-16 06:11:07.31249+02
2 | some_app | 0002_auto_20171016_1905 | 2017-10-17 02:05:48.979295+02
迁移(文件)是对增量更改的描述,也是可以评估自上次迁移以来 models.py
之间差异的信息,在运行 makemigrations
时进行比较。在某些表最初不受管理并且以后可以管理的情况下也足够了。 (因此也会记录非托管表。)
编辑: 一个示例:如何使用带有 --fake
的 sqlmigrate
来 fix a broken database by migrations(重新创建已删除的表)。
编辑: 示例:如果您决定删除某个应用程序的表并通过 migrate
重新创建它们(请注意并在下面查看我的评论),您可能还想重置该应用程序的所有迁移首先,包括初始迁移,使用伪迁移名称“zero”。
./manage migrate --fake some_app zero
。
sqlmigrate
的结果,也比快速删除整个数据库更好。