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模型建立了关系。
让我们来看看,中间表是个什么样子的:
首先有一列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
来源:https://blog.csdn.net/qq_24822271/article/details/125421883


猜你喜欢
- 如何把[1, 5, 6, [2, 7, [3, [4, 5, 6]]]]变成[1, 5, 6, 2, 7, 3, 4, 5, 6]?思考:-
- 本篇文档旨在介绍如何安装配置基于2台服务器的MySQL集群。并且实现任意一台服务器出现问题或宕机时MySQL依然能够继续运行。注意!虽然这是
- 共同点两者都接收两个参数,第一个参数是行的范围,第二个参数是列的范围不同点loc函数接收的是行/列的名称,iloc函数接收的是行/列的下标(
- 1.Apache2.2\conf\httpd.conf中释放: Include conf/extra/httpd-vhosts.conf(去
- 本文实例讲述了Python保存最后N个元素的方法。分享给大家供大家参考,具体如下:问题:希望在迭代或是其他形式的处理过程中对最后几项记录做一
- 一:文字加粗 倾斜的代码文字加粗的代码是: <b>你好</b>文字倾斜的代码是: <i>你好!</
- 秦歌这篇文章总结得很不错,俺挑刺来啦:1. 优先级的描述不严谨,有 !important 时,网页样式可以覆盖用户自定义样式。用户!impo
- 下面有python教程栏目为大家建立一个完美的python项目,希望可以帮助到大家,一起讨论进步~当开始一个新的 Python 项目时,大家
- Telnet 连接方式#!/usr/bin/env python# coding=utf-8import timeimport telnet
- 本文实例讲述了python登录pop3邮件服务器接收邮件的方法。分享给大家供大家参考。具体实现方法如下:import poplib, str
- format函数实现字符串格式化的功能基本语法为:通过 : 和 {} 来控制字符串的操作一、对字符串进行操作1. 不设置指定位置,按默认顺序
- 微信小程序中的下拉刷新,上拉加载的功能很常见,目前我知道的有两种可行的方法,一是scroll-view,二是整个页面刷新.今天说说第一种,自
- 前言Python中使用SSH需要用到OpenSSH,而OpenSSH依赖于paramiko模块,而paramiko模块又依赖于pycrypt
- 1.核心代码使用py2neo连接neo4j的方法:from py2neo import Graphgraph = Graph("h
- 本文以YOLOv5-6.1版本为例一、Add1.在common.py后加入如下代码# 结合BiFPN 设置可学习参数 学习不同分支的权重#
- 文本文件具备初步存放、编辑各类数据的能力,并可以持久保留和数据共享。1. 建立文件 建立文本文件有两种途径:一是通过Windows的“记事
- 说起元宵节,各位有没有觉得这是咱们中国人最浪漫的节日呢?国人向来拘谨古板,一年到头都是小心谨慎地过日子,唯有元宵节这天可以纵情豪放一把。东风
- 给定list,如何以空格/逗号等符号以分隔符输出呢?一般的,简单的for循环可以打印出list的内容:l=[1,2,3,4]for i in
- 上下文管理器是一种 Python 构造,它提供了一个类似 try-finally 的环境,具有一致的接口和方便的语法,例如通过&ld
- 一:使用Python中的urllib类中的urlretrieve()函数,直接从网上下载资源到本地,具体代码:import os,stati