如何在Django中表达一对多关系?

发布于 2024-11-27 14:35:33 字数 822 浏览 0 评论 0 原文

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

class Dude(models.Model):
    # 1 dude can have 0+ phone numbers
    numbers = models.OneToManyField('PhoneNumber')

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

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

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

我要替换什么OneToManyField (不存在)在模型中表示这种关系?我来自 Hibernate/JPA,其中声明一对多关系就像:

@OneToMany
private List<PhoneNumber> phoneNumbers;

如何在 Django 中表达这一点?

I'm defining my Django models right now and I realized that there wasn't a OneToManyField in the model field types. I'm sure there's a way to do this, so I'm not sure what I'm missing. I essentially have something like this:

class Dude(models.Model):
    # 1 dude can have 0+ phone numbers
    numbers = models.OneToManyField('PhoneNumber')

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

In this case, each Dude can have multiple PhoneNumbers, but the relationship should be unidirectional, in that I don't need to know from the PhoneNumber which Dude owns it, per se, as I might have many different objects that own PhoneNumber instances, such as a Business for example:

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

What would I replace OneToManyField (which doesn't exist) with in the model to represent this kind of relationship? I'm coming from Hibernate/JPA where declaring a one-to-many relationship was as easy as:

@OneToMany
private List<PhoneNumber> phoneNumbers;

How can I express this in Django?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

—━☆沉默づ 2024-12-04 14:35:33

要在 Django 中处理一对多关系,您需要使用 ForeignKey

关于 ForeignKey 的文档非常全面,应该可以回答您的所有问题:

https://docs.djangoproject.com/en/3.2/ref/models/fields/#foreignkey

示例中的当前结构允许每个 Dude有一个号码,每个号码属于多个 Dude(与 Business 相同)。


如果您想要相反的关系,则需要将两个 ForeignKey 字段添加到您的 PhoneNumber 模型中,一个添加到 Dude,一个添加到 商业。这将允许每个号码属于一个 Dude 或一个 Business,并且具有 DudeBusiness es能够拥有多个 PhoneNumber。我想这可能就是你所追求的:

class Business(models.Model):
    ...

class Dude(models.Model):
    ...

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

To handle One-To-Many relationships in Django you need to use ForeignKey.

The documentation on ForeignKey is very comprehensive and should answer all the questions you have:

https://docs.djangoproject.com/en/3.2/ref/models/fields/#foreignkey

The current structure in your example allows each Dude to have one number, and each number to belong to multiple Dudes (same with Business).


If you want the reverse relationship, you would need to add two ForeignKey fields to your PhoneNumber model, one to Dude and one to Business. This would allow each number to belong to either one Dude or one Business, and have Dudes and Businesses able to own multiple PhoneNumbers. I think this might be what you're after:

class Business(models.Model):
    ...

class Dude(models.Model):
    ...

class PhoneNumber(models.Model):
    dude = models.ForeignKey(Dude)
    business = models.ForeignKey(Business)
讽刺将军 2024-12-04 14:35:33

在 Django 中,一对多关系称为foreignkey。然而,它只能在一个方向上起作用,因此您不需要使用类 Dudenumber 属性,而是需要

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)

您就可以访问 Dude 对象的 PhoneNumber <代码>dd.phonenumber_set.objects.all(),然后对 Business 对象执行类似操作。

In Django, a one-to-many relationship is called ForeignKey. It only works in one direction, however, so rather than having a number attribute of class Dude you will need

class Dude(models.Model):
    ...

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

Many models can have a ForeignKey to one other model, so it would be valid to have a second attribute of PhoneNumber such that

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

You can access the PhoneNumbers for a Dude object d with d.phonenumber_set.objects.all(), and then do similarly for a Business object.

温柔嚣张 2024-12-04 14:35:33

更清楚地说 - Django 中没有 OneToMany,只有 ManyToOne - 这就是上面描述的foreignkey。您可以使用外键来描述一对多关系,但这非常不表达。

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

To be more clear - there's no OneToMany in Django, only ManyToOne - which is Foreignkey described above. You can describe OneToMany relation using Foreignkey but that is very inexpressively.

A good article about it:
https://amir.rachum.com/blog/2013/06/15/a-case-for-a-onetomany-relationship-in-django/

指尖上的星空 2024-12-04 14:35:33

姜戈足够聪明。实际上我们不需要定义oneToMany 字段。 Django 会自动为您生成它。我们只需要在相关表中定义一个foreignKey即可。换句话说,我们只需要使用foreignKey定义ManyToOne关系即可。

class Car(models.Model):
    # wheels = models.oneToMany() to get wheels of this car [**it is not required to define**].


class Wheel(models.Model):
    car = models.ForeignKey(Car, on_delete=models.CASCADE)  

如果我们想要获取特定汽车的车轮列表,我们将使用Python自动生成的对象wheel_set。对于汽车c,您将使用c.wheel_set.all()

Django is smart enough. Actually we don't need to define oneToMany field. It will be automatically generated by Django for you. We only need to define a foreignKey in the related table. In other words, we only need to define ManyToOne relation by using foreignKey.

class Car(models.Model):
    # wheels = models.oneToMany() to get wheels of this car [**it is not required to define**].


class Wheel(models.Model):
    car = models.ForeignKey(Car, on_delete=models.CASCADE)  

If we want to get the list of wheels of particular car, we will use Python's auto generated object wheel_set. For car c you will use c.wheel_set.all().

趁微风不噪 2024-12-04 14:35:33

您可以在 OneToMany 关系的多方(即 ManyToOne 关系)上使用外键,也可以在具有唯一约束的情况下使用 ManyToMany(在任何一方)。

You can use either foreign key on many side of OneToMany relation (i.e. ManyToOne relation) or use ManyToMany (on any side) with unique constraint.

本王不退位尔等都是臣 2024-12-04 14:35:33

虽然滚石的答案很好,简单且实用,但我认为它没有解决两件事。

  1. 如果 OP 想要强制一个电话号码不能同时属于 Dude 和 Business,
  2. 则由于在 PhoneNumber 模型而不是 Dude/Business 模型上定义关系,不可避免地会感到悲伤。当外星人来到地球时,我们想要添加一个外星人模型,我们需要修改PhoneNumber(假设外星人有电话号码),而不是简单地在外星人模型中添加一个“phone_numbers”字段。

引入内容类型框架,它公开了一些对象,使我们能够在 PhoneNumber 模型上创建“通用外键”。然后,我们可以在 Dude 和 Business 上定义反向关系,

from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models

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

    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    owner = GenericForeignKey()

class Dude(models.Model):
    numbers = GenericRelation(PhoneNumber)

class Business(models.Model):
    numbers = GenericRelation(PhoneNumber)

请参阅 docs 有关详细信息,也许可以查看 本文 获取快速教程。

另外,这里有一篇文章反对 使用通用 FK。

While rolling stone's answer is good, straightforward and functional, I think there are two things it does not solve.

  1. If OP wanted to enforce a phone number cannot belong to both a Dude and a Business
  2. The inescapable feeling of sadness as a result of defining the relationship on the PhoneNumber model and not on the Dude/Business models. When extra terrestrials come to Earth, and we want to add an Alien model, we need to modify the PhoneNumber (assuming the ETs have phone numbers) instead of simply adding a "phone_numbers" field to the Alien model.

Introduce the content types framework, which exposes some objects that allow us to create a "generic foreign key" on the PhoneNumber model. Then, we can define the reverse relationship on Dude and Business

from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models

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

    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    owner = GenericForeignKey()

class Dude(models.Model):
    numbers = GenericRelation(PhoneNumber)

class Business(models.Model):
    numbers = GenericRelation(PhoneNumber)

See the docs for details, and perhaps check out this article for a quick tutorial.

Also, here is an article that argues against the use of Generic FKs.

假情假意假温柔 2024-12-04 14:35:33

首先我们浏览一下:

01) 一对多关系:

ASSUME:

class Business(models.Model):
    name = models.CharField(max_length=200)
    .........
    .........
    phone_number = models.OneToMany(PhoneNumber) (NB: Django do not support OneToMany relationship)

class Dude(models.Model):
    name = models.CharField(max_length=200)
    .........
    .........
    phone_number = models.OneToMany(PhoneNumber) (NB: Django do not support OneToMany relationship)

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

注意:Django 不提供任何 OneToMany 关系。所以我们不能在Django中使用upper方法。但我们需要在关系模型中进行转换。那么我们能做什么呢?在这种情况下,我们需要将关系模型转换为反向关系模型。

这里:

关系模型= OneToMany

所以,反向关系模型= ManyToOne

注意:Django 支持ManyToOne 关系&在Django ManyToOne中用ForeignKey表示。

02)多对一关系:

SOLVE:

class Business(models.Model):
    .........
    .........

class Dude(models.Model):
    .........
    .........

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

注意:简单思考!

First of all we take a tour:

01) one-to-many relationship:

ASSUME:

class Business(models.Model):
    name = models.CharField(max_length=200)
    .........
    .........
    phone_number = models.OneToMany(PhoneNumber) (NB: Django do not support OneToMany relationship)

class Dude(models.Model):
    name = models.CharField(max_length=200)
    .........
    .........
    phone_number = models.OneToMany(PhoneNumber) (NB: Django do not support OneToMany relationship)

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

NB: Django doesn't provides any OneToMany relationship. So we can't use upper method in Django. But we need to convert in relational model. So what can we do? In this situation we need to convert relational model into reverse relational model.

Here:

relational model = OneToMany

So, reverse relational model = ManyToOne

NB: Django support ManyToOne relationship & in Django ManyToOne is represented by ForeignKey.

02) many-to-one relationship:

SOLVE:

class Business(models.Model):
    .........
    .........

class Dude(models.Model):
    .........
    .........

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

NB: THINK SIMPLY!!

小霸王臭丫头 2024-12-04 14:35:33

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

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(...)

这将确保该号码仅使用一次。

Actually, one-to-many relationship is very useful. I do something like this:

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(...)

This will ensure the number only use once.

隔纱相望 2024-12-04 14:35:33

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

这是一个更准确的实现:

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)

Whereas most answers here do pass in defining a relationship that allows you to define a OneToManyRelationship, they are actually in fact the definition of a ManyToManyRelationship.

Here is a more accurate implementation:

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)
救星 2024-12-04 14:35:33

如果“多”模型本身不能证明创建模型的合理性(这里不是这种情况,但它可能对其他人有利),另一种选择是通过 Django Contrib 包

Postgres 可以处理 数组JSON 数据类型,当许多时,这可能是处理一对多的一个很好的解决方法只能绑定到一个一个的单一实体。

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

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

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

If the "many" model does not justify the creation of a model per-se (not the case here, but it might benefits other people), another alternative would be to rely on specific PostgreSQL data types, via the Django Contrib package

Postgres can deal with Array or JSON data types, and this may be a nice workaround to handle One-To-Many when the many-ies can only be tied to a single entity of the one.

Postgres allows you to access single elements of the array, which means that queries can be really fast, and avoid application-level overheads. And of course, Django implements a cool API to leverage this feature.

It obviously has the disadvantage of not being portable to others database backend, but I thougt it still worth mentionning.

Hope it may help some people looking for ideas.

很酷又爱笑 2024-12-04 14:35:33

一对多关系意味着一个模型记录可以有许多与其自身关联的其他模型记录。

from django.db import models

class Menu(models.Model):
    name = models.CharField(max_length=30)

class Item(models.Model):
    menu = models.ForeignKey(Menu)
    name = models.CharField(max_length=30)
    description = models.CharField(max_length=100)

A one to many relationship implies that one model record can have many other model records associated with itself.

from django.db import models

class Menu(models.Model):
    name = models.CharField(max_length=30)

class Item(models.Model):
    menu = models.ForeignKey(Menu)
    name = models.CharField(max_length=30)
    description = models.CharField(max_length=100)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文