我现在正在定义我的Django模型,我意识到在模型字段类型中没有OneToManyField。我相信有办法做到这一点,所以我不确定我错过了什么。我基本上有这样的东西:

class Dude(models.Model):
    numbers = models.OneToManyField('PhoneNumber')

class PhoneNumber(models.Model):
    number = models.CharField()

在这种情况下,每个Dude可以有多个PhoneNumber,但这种关系应该是单向的,因为我不需要从PhoneNumber中知道哪个Dude拥有它,本质上,因为我可能有许多不同的对象拥有PhoneNumber实例,例如Business:

class Business(models.Model):
    numbers = models.OneToManyField('PhoneNumber')

我将在模型中用什么替换OneToManyField(它不存在)来表示这种关系?我来自Hibernate/JPA,在那里声明一对多关系非常简单:

@OneToMany
private List<PhoneNumber> phoneNumbers;

如何在Django中表达这一点?


当前回答

尽管这里的大多数答案在定义关系时传递了允许您定义OneToManyRelationship的关系,但它们实际上是多对多关系的定义。

下面是一个更准确的实现:

class Dude(models.Model):
    name = models.CharField(max_length=256, unique=True)

class PhoneNumber(models.Model):
    number = models.CharField(max_length=256, unique=True)

class DudePhoneNumbers(models.Model):
    dude = models.ForeignKey(Dude, related_name="phone_number_relations", on_delete=models.CASCADE)
    phone_number = models.OneToOneField(PhoneNumber, related_name="dude_relation", on_delete=models.CASCADE)

其他回答

实际上,一对多关系是非常有用的。我是这样做的:

class Dude(models.Model):
    number = models.ManyToManyField(PhoneNumber)

    def save(self, *args, **kwargs):
        if Dude.objects.get(number=self.number):
            raise Exception("Dude, this number has been used.")
        return super(Dude, self).save(*args, **kwargs)

class PhoneNumber(models.Model):
    number = models.CharField(...)

这样可以保证号码只使用一次。

更清楚地说,Django中没有OneToMany,只有ManyToOne,也就是上面描述的Foreignkey。你可以使用Foreignkey来描述OneToMany关系,但这是非常缺乏表现力的。

一篇关于它的好文章: https://amir.rachum.com/blog/2013/06/15/a-case-for-a-onetomany-relationship-in-django/

如果“许多”模型本身不能证明创建模型的合理性(这里不是这样,但它可能对其他人有益),另一种选择是依赖于特定的PostgreSQL数据类型,通过Django Contrib包

Postgres可以处理Array或JSON数据类型,当多个对象只能绑定到one的单个实体时,这可能是处理one - many的一个很好的变通方法。

Postgres允许您访问数组的单个元素,这意味着查询可以非常快,并避免应用程序级的开销。当然,Django实现了一个很酷的API来利用这个特性。

它显然有不能移植到其他数据库后端的缺点,但我认为它仍然值得一提。

希望它可以帮助一些人寻找想法。

您可以在多对多关系(即多对一关系)的多个方面使用外键,也可以在具有唯一约束的任何方面使用多对多(在任何方面)。

在Django中,一对多关系被称为ForeignKey。但是,它只在一个方向上工作,因此您需要的不是类Dude的number属性

class Dude(models.Model):
    ...

class PhoneNumber(models.Model):
    dude = models.ForeignKey(Dude)

许多模型都可以有一个指向另一个模型的ForeignKey,所以有第二个PhoneNumber属性是有效的,这样

class Business(models.Model):
    ...
class Dude(models.Model):
    ...
class PhoneNumber(models.Model):
    dude = models.ForeignKey(Dude)
    business = models.ForeignKey(Business)

您可以使用d.f onenumber_set.objects.all()访问Dude对象d的PhoneNumbers,然后对业务对象执行类似的操作。