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

 更新时间:2022年06月28日 10:53:00   作者:怎么会这样!  
我们在开发网站的时候,无可避免的需要设计实现网站的用户系统,我们需要实现包括用户注册、用户登录、用户认证、注销等功能,Django作为完美主义终极框架,它默认使用auth_user表来存储用户数据,下面我们来看看Django多对多使用through自定义中间表

多对多中间表详解

我们都知道对于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模型建立了关系。

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

首先有一列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让其充当另外的角色罢了。

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自定义中间表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • 简单了解Python matplotlib线的属性

    简单了解Python matplotlib线的属性

    这篇文章主要介绍了简单了解Python matplotlib线的属性,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-06-06
  • python同义词替换的实现(jieba分词)

    python同义词替换的实现(jieba分词)

    这篇文章主要介绍了python同义词替换的实现(jieba分词),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • Python中match语句的详细用法实例

    Python中match语句的详细用法实例

    match语句接受一个表达式并将其值与作为一个或多个 case 块给出的连续模式进行比较,下面这篇文章主要给大家介绍了关于Python中match语句的详细用法,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • anaconda如何创建和删除环境

    anaconda如何创建和删除环境

    这篇文章主要介绍了anaconda如何创建和删除环境,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • Python基础之列表常见操作经典实例详解

    Python基础之列表常见操作经典实例详解

    这篇文章主要介绍了Python基础之列表常见操作,结合实例形式详细分析了Python列表创建方式、内置函数与相关使用技巧,需要的朋友可以参考下
    2020-02-02
  • 使用python绘制地图的示例代码

    使用python绘制地图的示例代码

    要在Python中绘制地图,你可以使用各种库和工具包,其中最常用的是matplotlib和folium,本文就来给大家介绍一下如何使用python绘制地图,文章通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-08-08
  • python爬虫模块URL管理器模块用法解析

    python爬虫模块URL管理器模块用法解析

    这篇文章主要介绍了python爬虫模块URL管理器模块用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Python中使用sqlalchemy操作数据库的问题总结

    Python中使用sqlalchemy操作数据库的问题总结

    在探索使用 FastAPI, SQLAlchemy, Pydantic,Redis, JWT 构建的项目的时候,其中数据库访问采用SQLAlchemy,并采用异步方式,这篇文章主要介绍了在Python中使用sqlalchemy来操作数据库的几个小总结,需要的朋友可以参考下
    2024-08-08
  • Numpy中vstack()和hstack()的使用方式

    Numpy中vstack()和hstack()的使用方式

    文章详细介绍了Numpy中vstack()和hstack()两种数组拼接方法,vstack()是垂直堆叠数组,需保证除第一轴(行)外,数组形状相同,hstack()是按顺序堆叠数组,需保证除第二轴(列)外,数组形状相同,两者都可通过堆叠给定数组最后形成至少二维的数组
    2024-10-10
  • Python的in,is和id函数代码实例

    Python的in,is和id函数代码实例

    这篇文章主要介绍了python的in,is和id函数代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04

最新评论