何时在Django模型中使用一对一关系?

z9smfwbn  于 2023-08-08  发布在  Go
关注(0)|答案(3)|浏览(121)

我读过a fewplaces(见第二个答案),Django模型中的一对一关系几乎总是只用于继承,或者访问一个无法访问的模型(如Django用户模型)。
然而,似乎有这样的情况,你有一个对象,它总是有另一个对象的一个示例,你在逻辑上想要分离这两个对象。例如,您的应用程序存储了有关汽车的信息。每辆车只有一个司机,每个司机只能驾驶一辆车。把汽车和司机分成两个独立的模型是不是没有意义?

qlckcl4x

qlckcl4x1#

想象一下,你有一个公司,并使内部网工具列出所有员工,他们的职位,办公室,部门,工资等你可以在Django www.example.com中创建models.py一个类Employee,可能是这样的:

class Employee(models.Model):
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)
    position = models.CharField(max_length=255)
    office = models.CharField(max_length=20)
    salary = models.IntegerField()
    department = models.ForeignKey(Department, related_name='employees')

字符串
但由于某些原因你不希望工资对所有员工都能获得,也许在管理区有很多具有编辑者身份的人,决定外包给自己的模型,改变模型Employee:

class Employee(models.Model):
    # above attributes
    salary = models.OneToOneField(Salary)


当然还有其他方法可以隐藏这些信息,但是一种可能性是将这些信息分成两个表,即使它只是简单的1:1关系。
你的公司是一家软件公司,你引入了结对编程。每个员工都有一个结对编程伙伴。它可以是一个编程伙伴。所以你再调整一下你的模型:

class Employee(models.Model):
    # above attributes
    pair_programmer = models.OneToOneField('self')


这将是一个递归的一对一关系。
一对一关系在初学者教程中并不常见,也很难找到,但是如果有一些特定的要求,你会发现自己创建一对一关系来解决问题。
这是我工作中的一个真实的例子。我是生物信息学家,为微生物制作软件。它们按属和种分类。每个属可以包含一个或多个物种,但一个物种只能属于一个属。这是一个清晰的1:n关系。但现在,一个属有一个模式种,只有一个,而且只有一个。模式种可以属于一个属。在这里,我把models.OneToOneField,除了models.ForeignKey
不要太担心提前1:1的关系。当你遇到某个具体的问题时,你就会知道你是否需要1:1的关系。

x4shl7ld

x4shl7ld2#

Django文档给出了一个很好的答案:
例如,如果您正在构建一个“地点”数据库,您将构建非常标准的内容,如地址、电话号码等。在数据库里然后,如果您想在地点之上构建一个餐馆数据库,而不是在Restaurant模型中重复这些字段,您可以使Restaurant具有OneToOneFieldtoPlace(因为餐馆“是”一个地点;实际上,要处理这个问题,通常使用inherited每辆车都有一个司机,每个司机只驾驶一辆车。是否有意义分离汽车anance,这涉及到一个隐含的一对一的关系)。
Django使用OneToOne来建模继承(可能在内部使用它,但我还没有查看源代码)。我觉得如果django提供了一个工具,你可以用一种你可以防御的方式来使用这个工具,为什么不使用它呢?如果一辆车只有一个司机,那么使用django提供的工具(OneToOneField)在数据库中强制执行,这似乎是有道理的

wgeznvg7

wgeznvg73#

OneToOneField()在扩展User模型以添加额外字段时使用,如下所示。* 你可以看到我的答案解释如何使用OneToOneField()添加额外的字段:

# "account/models.py"

from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.OneToOneField(
        User, 
        verbose_name=_("user"), 
        on_delete=models.CASCADE
    )
    age = models.PositiveSmallIntegerField(_("age"))
    gender = models.CharField(_("gender"), max_length=20)
    married = models.BooleanField(_("married"))

字符串

相关问题