理解Django的多对一关系

介绍一种最常见的数据库关系:在Django中理解多对一。

什么是多对一关系?

在数据库设计中,多对一(或一对多)是指一个或多个实体之间的关系,其中一个实体可以连接多个实体。

让我们举个例子。考虑两个实体:母亲和女儿。正如我们从现实生活中所知,这两个实体在大多数情况下都是这样联系在一起的:

  • 每个女儿都有一个母亲

  • 一个母亲可以有许多女儿

所以我们这里有多对一,多是女儿,一是母亲。

用形似“乌鸦脚”的实体关系图可以这样描述:

在母亲那一边,你可以看到两条线,代表有且仅有一个。这是关系的“一面”。对应的,在女儿那边你可以看到鱼尾纹和一个圆圈。

圆圈是指任意数量的,也就是说,可以有零个、一个或多个女儿。严格地说,一个母亲至少应该有一个女儿才符合她的身份,但我想让你了解这种表示方法。

一只乌鸦的脚上面有一条直线(横线),这意味着至少有一个或多个,也就是说,关系的多面不能是空的。

现在,在用实体关系图对数据库建模之后,是时候编写实际的SQL指令了。在这个时代,你经常不想手动来做。

然而,通过实践来了解多对一关系是如何实现的很重要。让我们看看。

实践中的多对一关系

要在多对一关系中连接两个实体,我们需要在数据库中至少有两个表。以母亲为例,我们将有一个母亲表(示例用PostgreSQL方言显示):


女儿呢?这是“多”的一面。当然,我们可以创造另一张表,就像我们的母亲表一样:

但现在,我们该如何连接这两张表呢?这是用外键完成的。外键就像它的字面意思一样:它是一个从一个表指向另一个表的键(外键)。在添加之前,让我们删除旧表并创建一张包含名为mother_id列的新表:

mother_id 将为每个女儿提供相应的母亲。现在我们也准备好了添加约束:

通过这条语句我们向数据库发出指令:向列mother_id添加一个新外键,并让它指向mother表中的id列。

有了这些知识,现在让我们把注意力集中在Django的多对一上。

在Django中了解多对一

在测试之前,您需要创建一个新的Django项目和一个名为address_book的Django应用程序。

为了演示Django中的多对一,让我们再举一个例子。考虑两个实体:用户和联系人。对于这些实体,我们说:

  • 每个联系人属于一个用户

  • 一个用户可以有多个联系人  

想像一个地址簿,其中有许多用户通过昵称标识,每个用户的地址簿中可以有许多联系人:

joel89的通讯簿中有abc@abc.dev、jules@jules.io、joe@joe.dev

jules84的通讯簿中有def@abc.dev、vale@vale.io、john@john.dev

等等。转换为实体关系图,它变成:

现在要在Django应用程序中创建这些实体(模型),我们可以使用Django.db.models。我们创建了两个模型,每个模型都有相应的字段:

下一步,在Django配置中注册应用程序之后,我们运行python manage.py makemigrations和python manage.py migrate来在数据库中创建新表。

这将创建两个尚未连接的表。是时候添加外键了!

在Django理解多对一:外键

为了将这两个实体连接起来,以便将多个联系人连接到单个用户,Django提供了ForeignKey。可以在模型中添加以下字段:

在这里,我们添加一个名为user的新列,该列使用ForeignKey引用用户模型。确保运行python manage.py makemigrations和python manage.py migrate以应用更改。

需要注意的是,ForeignKey至少需要两个参数:

To描述要指向的实体。相应的,on_delete描述当关系的“一”被删除时数据库的行为。当“一”实体被删除时,“多”实体也被删除。

另一件需要注意的事情是,Django做的事情与其他框架有些不同。有些框架允许您有一对多关系,其中“多”的一面可以在“一”中定义。举个例子,拉雷维尔一对多就是这样。

最后的结果是相同的:“多”表将始终与“一”的外键相连接。

现在我们可以使用Django的ORM进行查询了。

在Django中理解多对一:创建相关对象

要测试结果,请进入Django控制台:

接下来导入两个模型,用户和联系人:

现在用一个用户填充数据库:

并创建一组与该用户相关的联系人:

创建新联系人是通过传递用户来作为create方法的参数,以将这两个实体绑定在一起。有了这些实体,我们现在可以进行查询了。

在Django中理解多对一:获取相关对象

要从我们的数据库访问用户,我们可以运行:

如果在我们的示例中只有一个用户,可以运行:

现在,获取与该用户相关的每个联系人该怎么做?使用Django ORM,我们可以使用表单下的查找功能,形式是.related_set,其中related是我们要访问的实体的名称。

因此,要获取用户的所有联系人(用户有许多联系人),我们可以运行:

此查询返回:

还有一种反向的查询:从联系人返回到相关用户(联系人有一个用户):

此查询返回我们联系人的相应用户: 

英文原文:https://www.valentinog.com/blog/many-to-one/ 
译者:QL
(完)





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值