在 Django 迁移期间收到“ValueError: Found wrong number of (0) of constraint for ...”

Posted

技术标签:

【中文标题】在 Django 迁移期间收到“ValueError: Found wrong number of (0) of constraint for ...”【英文标题】:Received "ValueError: Found wrong number (0) of constraints for ..." during Django migration 【发布时间】:2017-05-28 04:05:34 【问题描述】:

在使用 Django 1.7 迁移时,我遇到了一个在开发中有效但在生产中无效的迁移:

ValueError: Found wrong number (0) of constraints for table_name(a, b, c, d)

这是由AlterUniqueTogether 规则引起的:

   migrations.AlterUniqueTogether(
         name='table_name',
         unique_together=set([('a', 'b')]),
   )

阅读 Django 错误数据库中的错误等,似乎与数据库中现有的 unique_together 不匹配迁移历史记录有关。

如何解决此错误并完成我的迁移?

【问题讨论】:

【参考方案1】:

有人在修改unique_together 时可能会遇到此问题。基本上,表状态与迁移不一致。您可能需要使用 mysql shell 手动添加之前的约束。

【讨论】:

【参考方案2】:

在我的情况下,问题是表 dajsngo_migrations 中不存在先前的迁移。我添加了缺少的条目,然后新的迁移工作了

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。【参考方案3】:
    找到各自表的最新迁移文件,找到唯一的 一起,并替换当前的唯一约束字段。 使用 ./manage.py migrate your_app_name 迁移数据库。 恢复或撤消之前的迁移文件。

【讨论】:

【参考方案4】:

“数据库中的unique_together 与迁移历史不匹配” - 每次更改表上的索引时,它都会检查其先前的索引并将其删除。在您的情况下,它无法获取以前的索引。

解决方案- 1.您可以手动生成它 2.或者恢复到使用先前索引的代码并迁移。然后最后在代码中更改为新索引并运行迁移。(要处理的django_migration文件)

【讨论】:

【参考方案5】:

以防万一有人遇到此问题并且之前的答案尚未解决,在我的情况下,问题是当我修改唯一共同约束时,尝试迁移但数据不允许它(因为更严格的唯一一起约束)。但是,迁移设法从表中删除了唯一的共同约束,使其处于不一致的状态。我不得不迁移回零并在没有数据的情况下重新应用迁移。然后就顺利通过了。

总之,请确保您的数据在应用迁移之前能够接受新的约束。

【讨论】:

【参考方案6】:

另外值得检查的是,您只有预期数量的相关表的唯一索引。

例如,如果您的表有多个唯一索引,那么您应该删除它们以确保只有 1 个(或任何预期的唯一索引数量)存在迁移前索引。

检查 PostgreSQL 中给定表有多少唯一索引:

SELECT *
FROM information_schema.table_constraints AS c
WHERE
    c.table_name = '<table_name>'
    and c.constraint_type = 'UNIQUE'

【讨论】:

【参考方案7】:

我在将 CharField 切换为 ForeignKey 时遇到了类似的问题。一切都与这个过程一起工作,但我留下 Django 认为它仍然需要在新的迁移中更新unique_together。 (即使从 postgres 内部看起来一切都是正确的。)不幸的是,应用这个新迁移会产生类似的错误:

ValueError: Found wrong number (0) of constraints for program(name, funder, payee, payer, location, category)

最终对我有用的解决方法是注释掉该模型之前的所有 AlterUniqueTogether 操作。之后manage.py migrate 正常工作。

【讨论】:

【参考方案8】:

(Postgres 和 MySQL 答案)

如果您查看您的实际表(使用\d table_name)并查看索引,您会发现您的唯一约束的条目。这就是 Django 试图寻找和放弃的东西。但它找不到完全匹配的。

例如,

"table_name_...6cf2a9c6e98cbd0d_uniq" UNIQUE CONSTRAINT, btree (d, a, b, c)

在我的例子中,键 (d, a, b, c) 的顺序与它希望删除的约束 (a, b, c, d) 不匹配。

我回到了我的迁移历史并更改了原来的 AlterUniqueTogether 以匹配数据库中的实际顺序。

然后迁移成功完成。

【讨论】:

非常感谢分享这个。我正在使用 MySQL,并且在 DB 约束中的字段顺序与添加 unique_together 的原始迁移文件中的字段顺序不匹配时遇到了同样的问题。 我认为我会很棘手,将进行两次迁移:删除现有约束,然后添加新的扩展约束。但是由于这个错误,即使删除也不成功,所以我需要重新排序。 :P 哦,这对 MySQL 也是如此,我正在使用它 这非常有用,谢谢。实际上帮助我了解了有关迁移如何工作的更多信息 - 即,在反转时回顾以前的迁移。

以上是关于在 Django 迁移期间收到“ValueError: Found wrong number of (0) of constraint for ...”的主要内容,如果未能解决你的问题,请参考以下文章

Django 在迁移期间要求默认值

django 在服务器上的 syncdb 期间出错

如何在南迁移期间调用 django 模型类的静态方法

迁移期间的 Django NodeNotFoundError

Django 模型外键字段在测试期间的迁移中不可用

.env 文件中的环境变量在 django、heroku 的本地迁移期间不可用