【问题标题】:Django migration IntegrityError: invalid foreign key (but the data exists)Django迁移IntegrityError:无效的外键(但数据存在)
【发布时间】:2022-07-22 23:14:35
【问题描述】:

我正在逐步从 1.19 -> 2.2 及更高版本更新旧版 Django 应用程序。为了升级到 2.2,我刚刚将 on_delete=models.CASCADE 添加到所有没有错误的 models.ForeignKey 字段(显然,我还必须对现有迁移进行追溯......)。

可能与此相关/无关,当我运行 manage.py migrate 时,Django 抛出以下错误(为简洁起见,我缩短了表/字段名称):

django.db.utils.IntegrityError: The row in table 'X' with primary key '3' has an invalid foreign key: X.fieldname_id contains a value '4' that does not have a corresponding value in Y__old.id.

特别注意 db 表的 __old.id 后缀,Django 期望包含 ID 为 4 的行。手动检查数据库时,表Y 确实包含一个有效行,id 为4!我假设,为了支持迁移,Django 正在制作一些以__old 为后缀的临时表,并且不知何故无法迁移所述数据?

有问题的 db 行 Y 非常简单:一个字符、布尔值和数字列。

编辑:似乎与使用 SQLite 的旧 Django bug 有关。不知道如何解决。 Django 2.1.15 似乎没有出现,在 Django 2.2 中开始出现。

【问题讨论】:

    标签: django django-models django-migrations


    【解决方案1】:

    这不是一个理想的解决方案,但是您可以手动从数据库中删除该行或将外键的值设置为临时值,然后迁移然后恢复原始值。

    【讨论】:

      【解决方案2】:

      这个问题是由上面提到的 Django 错误引起的,但是如果你得到迁移错误,你的数据库已经坏了。

      当您将 DB 转储到 SQL 时,您可以看到 REFERENCES 语句指向以 __old 结尾的表,但这些表实际上并不存在:

      $> sqlite3 mydb.db .dump | grep '__old'
      
      CREATE TABLE IF NOT EXISTS "company" [...]"account_id" integer NULL REFERENCES "account__old" ("id") [...]
      

      幸运的是,只需删除__old 并将其转储到新数据库中即可轻松修复数据库。这可以通过sed 自动完成:

      sqlite3 broken.db .dump | sed 's/REFERENCES "\(.*\)__old"/REFERENCES "\1"/g' | sqlite3 fixed.db
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-12
        相关资源
        最近更新 更多