Py学习  »  Django

理解Django的多对一关系

Python程序员 • 3 年前 • 382 次点击  


介绍一种最常见的数据库关系:在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

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/57323
 
382 次点击