django.db.utils.ProgrammingError:外键约束中引用的列“id”不存在或不允许表有多个主键

问题描述 投票:0回答:1

Postgres14 上的 Django4。最新版本 2023 年 11 月这个bug困扰了我一整天

  • 我扫描了 django GitHub 上的 django 项目问题
  • 在 SO 和其他 FQA 平台上进行大量研究
  • 问gpt

没有找到有用的解决方案。因此写一个公会,可以方便将来的访问者。

django postgresql primary-key one-to-one
1个回答
0
投票

所以Postgres与SQLite3的不同之处主要在于主键。如果你们有一对一的关系

  • app = models.OneToOneField(project)

在 SQLite3 中,当你调用

app.pk == app.project.pk
时,它总是 true。这允许你写这样的东西:
user = user.objects.get(pk=profile_pk)
,因为它们都是一致的。

但是Postgres不同,一对一将不再有一致的主键,这意味着你必须指定

app = models.OneToOneField(project, primary_key=True)
,才能使两个表具有一致的pks,以支持你编写的视图逻辑而无需手动更改它们(比如通过一对一 pk 获取另一个模型实例,因为它们应该是相同的)。

但是如果你定义了其他现有的一对一关系,这是不可能的:例如模型A在模型B上有一个一对一的字段,并且具有一致的pks,并且模型B与模型C有一对一的字段,并且没有一致的一致的峰。这里后端 sql 执行器默认会尝试实例化另一个 pk 字段以允许您建立此数据库关系。然而,这被认为是 django 无法管理的做法,因此提出了一个例外:

multiple primary keys not allowed

此外,如果您尝试在迁移的同时声明引用该

one-to-one messed up
表的 pk 的新模型模式,那么它将是
foreign key constraint does not exist


幸好有解决方案,无需删除数据库。

  1. 找到您正在迁移的应用程序,将其恢复到上次迁移的ok状态

python manage.py migrate app 0002_initial

  1. 删除生成的新迁移文件,仔细检查模型,最好删除该模型中所有带有

    primary_key=True
    的一对一字段。

  2. 进行迁移并迁移该应用程序。

© www.soinside.com 2019 - 2024. All rights reserved.