Django 中 OneToOneField 的使用

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

我对

OnetoOneField
的用法很困惑。 我认为这是针对给定记录只能有 1 个对另一个表的引用的情况。 例如,一个孩子有 1 个父母。

但 Django 似乎将定义为 OneToOne 的字段作为表的主键,这意味着它具有唯一约束。 这没有任何意义。 任何给定的孩子只有 1 个父母。 但同一个父母可能有不止 1 个孩子。 父项的 FK 在整个子表中不会是唯一的

我想使用 OneToOne 而不是foreignkey来强制执行一对一方面,而不是foreignkey,它是一对多(任何给定的孩子可以有超过1个父母)。

我的理解有误吗? 我是否应该重新使用foreignkey并确保我的代码强制执行1-1?

我发现这些其他链接提出了同样的问题,但不确定我是否看到了明确的答案 为什么有人会在一对一关系(OneToOneField)上设置primary_key=True? Django 中的OneToOneField() 与ForeignKey()

python django django-models one-to-one
1个回答
0
投票

A

OneToOneField
可能有点误导,实际上它是一个零/一对一字段。它通常用于将模型 A 的实例与模型 B 的实例关联起来,但没有两个 A 实例可以引用同一个 B 实例。一个典型的用例是,例如,如果您有一个
Employee
的模型,并且对于某些
Employee
,您必须保存额外的数据。但这通常是一种反模式:如果您可以控制模型B(因为它没有在不同的包中实现),则您不能向B添加(可为空的)字段,因此您可以带有额外数据的模型 A,并将
OneToOneField
A 指向 B。如果字段数量很大,并且具有相关记录 AB 记录数量很少,也可以使用此方法。在这种情况下,创建额外的可为空字段可能会极大地破坏数据库。在 Django 默认包(
django.contrib
)中根本不使用它。

然而

A

OneToOneField
有一个用例,Django 在隐藏事项中使用
OneToOneField
模型继承 [Django-doc]。事实上,如果你制作两个模型:

class Foo(models.Model):
    pass


class Bar(Foo):
    pass

然后这是两个具体模型。 Django 通过创建两张表来实现这一点,一张用于

foo
,一张用于
bar
Bar
的主键将是引用
OneToOneField
表的
Foo
。因此,它们共享相同的“id 空间”,并且还确保不会为一个
Bar
生成两个
Foo
。然而,如果
Qux
也是
Qux
的子类,则它不会阻止使用相同的 id 创建记录
Foo
,因此它不是表示继承的“完美”方式。此外,关系数据库中的继承通常也不是一个好主意,因为它需要额外的 JOIN。

总结一下:

OneToOneField
通常用于将数据添加到我们无法太多控制的现有模型中,或者当包含额外数据的记录数量很少时,并且会耗尽存储空间。但应该明智地使用它。

轶事:我曾经这样做过,因为 Django 并没有非常清楚哪个会话属于哪个用户。它被编码在会话数据中,但不容易过滤,例如哪些会话属于某个用户。然后我用

OneToOneField
来引用
Session
,以防止创建大量额外记录。

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