Django细致讲解多对多使用through自定义中间表方法

作者:怎么会这样! 时间:2022-12-12 17:22:41 

多对多中间表详解

我们都知道对于ManyToMany字段,Django采用的是第三张中间表的方式。通过这第三张表,来关联ManyToMany的双方。下面我们根据一个具体的例子,详细解说中间表的使用。

默认中间表

class Person(models.Model):
   name = models.CharField(max_length=128)
   def __str__(self):
       return self.name
class Group(models.Model):
   name = models.CharField(max_length=128)
   members = models.ManyToManyField(Person)
   def __str__(self):
       return self.name

在Group模型中,通过members字段,以ManyToMany方式与Person模型建立了关系。

让我们来看看,中间表是个什么样子的:

Django细致讲解多对多使用through自定义中间表方法

首先有一列id,这是Django默认添加的,没什么好说的。然后是Group和Person的id列,这是默认情况下,Django关联两张表的方式。如果你要设置关联的列,可以使用to_field参数。

可见在中间表中,并不是将两张表的数据都保存在一起,而是通过id的关联进行映射。

通过through自定义中间表

一般情况,普通的多对多已经够用,无需自己创建第三张关系表。但是某些情况可能更复杂一点,比如如果你想保存某个人加入某个分组的时间呢?想保存进组的原因呢?

Django提供了一个through参数,用于指定中间模型,你可以将类似进组时间,邀请原因等其他字段放在这个中间模型内。例子如下:

modle:

from django.db import models
class Person(models.Model):
   name = models.CharField(max_length=128)
   def __str__(self):
       return self.name
class Group(models.Model):
   name = models.CharField(max_length=128)
   members = models.ManyToManyField(Person, through='Membership')
   def __str__(self):
       return self.name
class Membership(models.Model):
   person = models.ForeignKey(Person, on_delete=models.CASCADE)
   group = models.ForeignKey(Group, on_delete=models.CASCADE)
   date_joined = models.DateField()  # 进组时间
   invite_reason = models.CharField(max_length=64)  # 邀请原因

view:

class PersonViews(ModelViewSet):
   queryset = Person.objects.filter()
   serializer_class = PersonSerializers
class GroupViews(ModelViewSet):
   queryset = Group.objects.filter()
   serializer_class = GroupSerializers
class MembershipViews(ModelViewSet):
   queryset = Membership.objects.filter()
   serializer_class = MembershipSerializers

serializer:

from .models import Person, Group, Membership
class MembershipSerializers(serializers.ModelSerializer):
   class Meta:
       model = Membership
       fields = '__all__'
class PersonSerializers(serializers.ModelSerializer):
   class Meta:
       model = Person
       fields = '__all__'
class GroupSerializers(serializers.ModelSerializer):
   def to_representation(self, instance):
       representation = super(GroupSerializers, self).to_representation(instance)
       representation['members'] = []
       for i in PersonSerializers(instance.members, many=True).data:
           reason = MembershipSerializers(instance.membership_set.get(group=instance.id, person=i['id'])).data['invite_reason']
           i['invite_reason'] = reason
           representation['members'].append(i)
       return representation
   class Meta:
       model = Group
       fields = '__all__'

从Membership角度,他是建立量到两个模型(Group,Person)的多对1关系,Django在启动时,会自动在其关联的模型上建立"[model]_set"的属性,就想常规的多对一关系一样——实际上他就是常规的多对一关系,只不过Person让其充当另外的角色罢了。

Django细致讲解多对多使用through自定义中间表方法

reason = MembershipSerializers(instance.membership_set.get(group=instance.id, person=i[‘id’])).data[‘invite_reason’]

instance.membership_set.get(group=instance.id, person=i[‘id’]) group和person联合查出邀请原因

person和group模型上membership对象的默认名称都将为membership_set.所以通过instance.membership_set.get()可以查看group下的所有关系

person下的所有membership:

# def to_representation(self, instance):
   #     representation = super(PersonSerializers, self).to_representation(instance)
   #     representation['reason'] = MembershipSerializers(instance.membership_set, many=True).data
   #     return representation

Django细致讲解多对多使用through自定义中间表方法

Django细致讲解多对多使用through自定义中间表方法

来源:https://blog.csdn.net/qq_24822271/article/details/125421883

标签:Django,through,自定义,中间表
0
投稿

猜你喜欢

  • Antd的table组件表格的序号自增操作

    2024-04-28 09:31:40
  • 音频处理 windows10下python三方库librosa安装教程

    2023-10-12 08:29:50
  • 最大限度优化你的Asp性能

    2007-10-01 18:04:00
  • Python之ascii转中文的实现

    2023-08-24 19:39:12
  • python smtplib模块自动收发邮件功能(二)

    2023-09-29 19:52:28
  • Python 异步如何使用等待有时间限制协程

    2022-02-12 09:29:28
  • 如何添加一个mysql用户并给予权限详解

    2024-01-17 06:09:36
  • 如何基于python实现年会抽奖工具

    2022-01-28 04:24:42
  • golang 并发安全Map以及分段锁的实现方法

    2024-04-28 10:45:44
  • javascript 得到变量类型的函数

    2024-04-30 08:53:34
  • 插件下载安装系列Eclipse/IDEA/谷歌/火狐安装插件

    2022-05-13 03:46:18
  • python多线程之事件Event的使用详解

    2022-12-21 11:46:10
  • 让ExtJs的combobox不显示HTML……

    2009-05-31 17:01:00
  • python实现矩阵和array数组之间的转换

    2022-03-19 16:31:21
  • python实现密码验证合格程序的思路详解

    2022-12-10 05:07:38
  • JavaScript—window对象使用示例

    2024-05-08 09:39:34
  • 详解Python如何优雅地解析命令行

    2021-02-16 01:53:59
  • mysql left join快速转inner join的过程

    2024-01-26 19:08:17
  • jquery和css3中的选择器nth-child使用方法和用途示例

    2024-04-25 13:11:35
  • 浅谈django2.0 ForeignKey参数的变化

    2022-03-26 10:11:30
  • asp之家 网络编程 m.aspxhome.com