【问题标题】:Django migrate --fake and --fake-initial explainedDjango migrate --fake 和 --fake-initial 解释
【发布时间】:2018-03-28 02:51:34
【问题描述】:

我已经使用 Django 大约 2 年了,有一个我一直害怕使用的功能:伪造迁移

我几乎到处都看过,我能得到的最多信息来自documentation,它指出:

--假的

告诉 Django 将迁移标记为已应用或 未应用,但没有实际运行 SQL 来更改您的 数据库架构。

这是供高级用户操作当前 如果他们手动应用更改,则直接迁移状态;是 警告使用 --fake 会冒着迁移状态的风险 表进入需要手动恢复的状态 迁移运行正常。

--fake-initial

如果所有数据库都允许 Django 跳过应用程序的初始迁移 具有由所有 CreateModel 创建的所有模型的名称的表 该迁移中的操作已经存在。此选项旨在 用于第一次对数据库运行迁移时使用 预先存在迁移的使用。但是,此选项不检查 用于匹配表名之外的匹配数据库模式等 只有当您确信您现有的架构时才能安全使用 与您初始迁移中记录的内容相匹配。

我大致了解了为什么要使用此功能。但是,我不明白它说这是仅供高级用户使用的部分。

谁能解释幕后发生的事情以及为什么需要手动恢复。

注意

我不是在寻找在伪造迁移时运行的确切原始 SQL 查询。我只是在寻找幕后发生的事情的一般概念,也许是一个为什么假装迁移的例子 将导致makemigrations 无法正常工作的状态。

【问题讨论】:

  • 我认为值得一提的是,当您运行 --fake 时,是否将迁移标记为已应用,在 django_migrations 表中定义,Django 跟踪应用程序的所有已应用迁移,其中迁移文件的name 以及应用的时间。我花了一段时间才弄清楚这一点,因为文档并不清楚我在这里介绍的这个细节。

标签: django django-models django-migrations


【解决方案1】:

如果您需要将具有相似模型的两个分支组合或在它们之间切换,则它与类似于源代码(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 时进行比较。在某些表最初不受管理并且以后可以管理的情况下也足够了。 (因此也会记录非托管表。)

编辑:一个例子:sqlmigrate--fake 如何用于fix a broken database by migrations(重新创建已删除的表)。

编辑: 示例:如果您决定删除某些应用程序的表并通过 migrate 再次创建它们(请注意并在下面查看我的评论),您可能还想重置所有迁移首先使用伪迁移名称“zero”对该应用程序进行迁移,包括初始迁移。
./manage migrate --fake some_app zero

【讨论】:

  • 感谢您的回答!它帮助我看到了伪造迁移的真实情况,但我仍然想知道在伪造迁移时幕后发生了什么。
  • @hynekcer 我对您上次的编辑有疑问,当它们与我的数据库历史同步时,为什么我要“重置所有迁移”?最近我遇到了类似的问题,将独特的属性添加到表中的一行。当我运行迁移时,我收到错误:“ProgrammingError:关系“...唯一”已经存在”,但是当我删除所有迁移并重播此步骤时,它通过了吗?我必须指出,我的两个项目都在同一个数据库上工作,并且我在两个应用程序中都添加了唯一属性。
  • @Unknown123 我应该在最后一个示例中添加一些警告“并且您知道自己在做什么”,例如如果它在没有重要数据的情况下正在开发中,并且同步被严重破坏以至于无法进行向前或向后迁移,那么假迁移到“零”并删除一些表可能是一个更好的解决方案,而不是缓慢编辑 sqlmigrate 的结果并且比快速删除整个数据库更好。
  • 如果你的两个项目在同一个数据库上工作,那么使用相同的 models.py 和相同的迁移目录很重要。在一个项目中迁移的内容也将在第二个项目中迁移。如果无法使用通用模型,那么如果可能会很糟糕,并且您永远无法在第二个数据库中运行迁移并仅手动运行 sqlmigrate 的一小部分并设置 Meta: managed=False。
  • 事实上,在很多情况下你需要伪造迁移。特别是当您想在另一台服务器中使用来自一台服务器的数据库转储时。当您遇到难以调试且只能在生产服务器中重现的错误时,伪造非常有用。由于 git 冲突而弄乱迁移文件是因为 .gitignore 文件配置错误。作为伪造迁移的用例,这不是一个很好的例子
猜你喜欢
  • 2017-07-30
  • 1970-01-01
  • 2021-06-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-06
  • 2019-03-05
  • 2020-03-18
  • 2015-08-03
相关资源
最近更新 更多