三、DRF关联表的序列化(通过主表,查询从表数据)

news2025/1/13 2:49:26

官方文档:

Serializers - Django REST framework中文站点

上一章:

 二、Django REST Framework (DRF)序列化&反序列化_做测试的喵酱的博客-CSDN博客

一、前提

models.py

class MiaoClass(models.Model):
    id = models.AutoField(primary_key=True, verbose_name='id', help_text='id')
    classname = models.CharField(max_length=20, verbose_name='班级名称', help_text='班级名称')
    clasleader = models.CharField(max_length=10, verbose_name='班主任姓名', help_text='班主任姓名')
    classcode = models.IntegerField(unique=True, verbose_name='班级code', help_text='班级code')
    ifopens = models.BooleanField(default=True, verbose_name='是否开学', help_text='是否开学')
    classrate = models.IntegerField( verbose_name='班费', help_text='班费')

    class Meta:
        # i.db_table指定创建的数据表名称
        db_table = 'tb_class'
        # 为当前数据表,设置中午呢描述
        verbose_name = "班级表"
        verbose_name_plural = "班级表"

二、查询主表数据时,显示从表的主键数据(PrimaryKeyRelatedField)

  1. 可以通过定义PrimaryKeyRelatedField来获取关联表的外键值
  2. 如果通过父表获取从表数据,默认需要使用从表模型类名小写_set作为序列化器中的关联字段名称
  3. 如果在定义模型类的外键字段时,指定了realated_name参数,那么会把realated_name参数作为序列化器类中的关联字段。

 

2.1 主表的序列化器类

 serializers.py

class ClassSerializer(serializers.Serializer):
    id = serializers.IntegerField(label='班级id', help_text='班级id')
    classname = serializers.CharField(max_length=20, label='班级名称', help_text='班级名称')
    clasleader = serializers.CharField(max_length=10, label='班主任姓名', help_text='班主任姓名')
    classcode = serializers.IntegerField(label='班级code', help_text='班级code')
    ifopens = serializers.BooleanField(label='是否开学', help_text='是否开学')
    classrate = serializers.IntegerField(label='班费', help_text='班费')
    miaostudent_set = serializers.PrimaryKeyRelatedField(label='学生id', help_text='学生id',read_only=True,many=True)

2.2 查询主表时,显示从表的主键数据(PrimaryKeyRelatedField)

实现功能:

在查询主表时,需要显示主表对应的从表数据。

实现方法:

在定义主表的序列化器类时,需要新增一个关联从表的字段,命名为 【从表名模型类称小写_set】 ,值为  关键字 serializers.PrimaryKeyRelatedField 。

最后取值为从表的主键字段。

   miaostudent_set = serializers.PrimaryKeyRelatedField(label='学生id', help_text='学生id',read_only=True,many=True)

1、该字段,在输入时不不需要输入该字段。在序列化输出时,需要显示该字段,所以使用

read_only=True,

2、一条主表数据,可能对应多条从表数据,所以需要使用 many=True

2.2.1 构建请求

views.py


class ClassesView(View):

    # 查询所有数据
    def get(self,request):
        # 获取列表数据
        queryset = MiaoClass.objects.all()
        print(queryset)
        serializer = ClassSerializer(instance=queryset, many=True)
        return JsonResponse(serializer.data, safe=False)

class ClassesDetailView(View):
    def get(self, request, pk):
        # 1、需要校验pk在数据库中是否存在

        # 2、从数据库中读取项目数据
        try:
            class_obj = MiaoClass.objects.get(id=pk)
        except Exception as e:
            return JsonResponse({'msg': '参数有误'}, status=400)
        serializer = ClassSerializer(instance=class_obj)

        return JsonResponse(serializer.data)

urls.py

    # 样式:类视图.as_view()
    path("classes/",views.ClassesView.as_view()),
    path('classes/<int:pk>/',views.ClassesDetailView.as_view()),

 

 miaostudent_set 的值,显示的是从表的主键值

2.3 自定义主表中的从表属性名称

在上面的结果中,显示的值是 miaostudent_set (从表名模型类称小写_set),

对于调用者来说,不懂这个字段的含义,我们想自定义一下这个字段的名称。

如定义为sid。

1、先修改models.py 中学生表模型类的外键 ,关联名称related_name='sid'

class MiaoStudent(models.Model):
    sname = models.CharField(max_length=20, verbose_name='学生姓名', help_text='学生姓名')
    sgender = models.BooleanField(verbose_name='性别', help_text='性别')
    sage = models.IntegerField(verbose_name='年龄', help_text='年龄')
    sid = models.IntegerField(unique=True, verbose_name='学号', help_text='学号')
    sscore = models.IntegerField( verbose_name='成绩', help_text='成绩')
    classid = models.ForeignKey('miaoschool.MiaoClass',on_delete=models.CASCADE,verbose_name='班级id',
                                help_text='班级id',
                                related_name='sid')
classid = models.ForeignKey('miaoschool.MiaoClass',on_delete=models.CASCADE,verbose_name='班级id',
                            help_text='班级id',
                            related_name='sid')

2、序列化器中,使用sid 字段

sid = serializers.PrimaryKeyRelatedField(label='学生id', help_text='学生id', read_only=True, many=True)
class ClassSerializer(serializers.Serializer):
    id = serializers.IntegerField(label='班级id', help_text='班级id')
    classname = serializers.CharField(max_length=20, label='班级名称', help_text='班级名称')
    clasleader = serializers.CharField(max_length=10, label='班主任姓名', help_text='班主任姓名')
    classcode = serializers.IntegerField(label='班级code', help_text='班级code')
    ifopens = serializers.BooleanField(label='是否开学', help_text='是否开学')
    classrate = serializers.IntegerField(label='班费', help_text='班费')
    # miaostudent_set = serializers.PrimaryKeyRelatedField(label='学生id', help_text='学生id',read_only=True,many=True)
    sid = serializers.PrimaryKeyRelatedField(label='学生id', help_text='学生id', read_only=True, many=True)

再次发起请求

 返回值变成了cid

 

2.4 PrimaryKeyRelatedField

PrimaryKeyRelatedField 中,需要指定 read_only=True, 或者 queryset

方式一:指定read_only=True

只做序列化输出,(在创建数据时,用户不需要输入该字段,在用户查询数据时,展示该字段的数据)

 sid = serializers.PrimaryKeyRelatedField(label='学生id', help_text='学生id', read_only=True, many=True)

方式二:指定queryset=从表模型类.objects.all()

    sid = serializers.PrimaryKeyRelatedField(label='学生id', help_text='学生id',
                                             queryset = MiaoStudent.objects.all(),
                                             write_only=True,
                                             many=True)

指定queryset=关联表的查询集对象,用于对参数进行校验。

三、 查询主表时,显示从表模型类的__str__

 实现功能:

在从表模型类中,定义__str__方法。在主表中,查询数据时,将从表的__str__数据输出。

1、从表模型类,需要定义 __str__方法

    def __str__(self):
        return f"姓名:{self.sname},性别:{self.sgender},年龄:{self.sage},分数:{self.sscore}"
class MiaoStudent(models.Model):
    sname = models.CharField(max_length=20, verbose_name='学生姓名', help_text='学生姓名')
    sgender = models.BooleanField(verbose_name='性别', help_text='性别')
    sage = models.IntegerField(verbose_name='年龄', help_text='年龄')
    sid = models.IntegerField(unique=True, verbose_name='学号', help_text='学号')
    sscore = models.IntegerField( verbose_name='成绩', help_text='成绩')
    classid = models.ForeignKey('miaoschool.MiaoClass',on_delete=models.CASCADE,verbose_name='班级id',
                                help_text='班级id',
                                related_name='sid')
    class Meta:
        # i.db_table指定创建的数据表名称
        db_table = 'tb_student'
        # 为当前数据表,设置中午呢描述
        verbose_name = "学生信息表"
        verbose_name_plural = "学生信息表"

    def __str__(self):
        return f"姓名:{self.sname},性别:{self.sgender},年龄:{self.sage},分数:{self.sscore}"

2、在父表的序列化器类中,需要指定StringRelatedField(many=True) 

sid = serializers.StringRelatedField(many=True)

注意:

 StringRelatedField 中,默认添加了read_only=True,该字段只序列化输出

3、接口请求,查看返回数据

 

四、 查询主表时,显示从表的指定字段值

1、实现功能:

查询主表数据,同时显示从表中指定的字段。

如我想要展示从表中的学生姓名字段sname

2、SlugRelatedField(slug_field='')指定从表字段,只做序列化输出。(只读数据)

sid = serializers.SlugRelatedField(slug_field='sname', many=True, read_only=True)

3、 SlugRelatedField(slug_field='')指定从表字段,反序列化输出。写数据时进行校验

需要指定queryset,同时关联字段必须有唯一约束。

sid = serializers.SlugRelatedField(slug_field='sname',many=True,queryset=MiaoStudent.objects.all())

五、查询主表时,显示从表的指定的多个字段值

1、需要展示从表的哪几个字段,我们可以单独再定义一个序列化器类。

如我想显示从表的 sname 与score字段。

定义一个序列化器类,只包含这两个字段。

class StudentINfoSerializer(serializers.Serializer):
    sname = serializers.CharField(label='学生姓名', help_text='学生姓名', max_length=10, min_length=1)
    sscore = serializers.IntegerField(label='学生成绩', help_text='学生成绩', max_value=100, min_value=0)

2、在主表的序列化器中, miaostudent_set = StudentSerializer()

miaostudent_set = StudentSerializer(read_only=True,many=True)

 注意:

  1. 自定义序列化器是Field的子类。
  2. 在自定义序列化器中,定义字段时,字段必须是Field或者Field的子类,所以在自定义序列化器中,定义字段时,字段也可以是一个序列化器类。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/560815.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Springboot +spring security,实现前后端分离,使用JSON数据格式登录(将表单提交方式改成json格式登录)

一.简介 在前面的文章中&#xff0c;我们使用表单方式完成登录提交&#xff0c;但是目前基本都是前后端分离项目&#xff0c;很少使用表单提交的方式&#xff0c;基本都是json方式&#xff0c;使用ajax提交&#xff0c;那么我们怎么将表单提交方式改成json格式登录呢&#xff…

语雀批量导出 mardown 文档(不需要 token)

推荐一个小工具&#xff1a;renyunkang/yuque-exporter &#xff0c;可以不借助语雀超级会员的 token 实现批量导出 markdown 文档。我的语雀知识库又可以实现免费迁移了&#xff0c;点个小星星支持一下。 说明&#xff1a; 这是一个基于puppeteer 来模拟用户在浏览器的操作…

基于深度强化学习的目标驱动型视觉导航泛化模型

深度强化学习在目标驱动型视觉导航的泛化 参考论文《Towards Generalization in Target-Driven Visual Navigation by Using Deep Reinforcement Learning》 文章目录 深度强化学习在目标驱动型视觉导航的泛化1. 目标驱动型视觉导航问题2. 创新点和解决的问题2.1 创新点2.2 解…

随身WIFI折腾日记(四)---拓展USB接口读取U盘内容

五、USB行为控制 随身WIFI对外交互的接口只有WIFI和USB接口。如果要想接入其他硬件设备&#xff0c;拓展USB接口至关重要&#xff0c;对于USB接口的控制&#xff0c;参考如下链接: openstick项目官方教程:控制usb行为 HandsomeMod/gc: A Simple Tool To Control Usb Gadget …

Opencv C++图像处理:点多边形测试 + 矩 + 凸包 + 映射 + 反向投影

文章目录 1、点多边形测试1.1、计算像素点是在轮廓内部、外部或边界上&#xff1a;cv::pointPolygonTest()1.2、计算最小值和最大值及其位置&#xff1a;cv::minMaxLoc()1.3、实战案例 2、矩2.1、计算多边形或光栅化形状的三阶以下的所有力矩&#xff1a;cv::moments()2.2、计算…

Regularization

在图像中的特征处理&#xff1a; 平均亮度的去除 SVD Whiten PCA 参数初始化策略 数据归一化&#xff1a; 标准归一化缩放归一化PCA/SVD 数据归一化对梯度的影响 归一化后&#xff0c;可以更快的搜索到最优值点 正则化 数据增强与早停 图像数据的增强主要是通过算法…

测试新手如何去学习接口自动化测试 ?从这一套测试框架开始 。

接口自动化测试框架系列之整体介绍 1.接口自动化测试1.自动化框架概述2.搭建自动化测试框架3.测试框架中所使用到的技术 1.接口自动化测试 自动化测试虽然是测试中比较热的一门技术 &#xff0c;但凡一个测试岗位&#xff0c;你几乎都能看到有自动化测试的要求 。但不得不说&a…

关于深度学习方面的一些概念

1、自学习&#xff08;self-taught learning&#xff09;与半监督学习   自学习(self-taughtlearning)是不要求未标注数据 X u X_u Xu​和已标注数据 X l X_l Xl​来自同样的分布。另外一种带限制性的方式也被称为半监督学习&#xff0c;它要求 X u X_u Xu​和 X l X_l Xl​服…

[快速入门前端17] CSS 选择器(6) 选择器总结

基本选择器 选择器说明语法通配符作用范围为所有标签&#xff0c;用于页面整体样式* { color: red }元素作用于同种标签&#xff0c;不能进行差异化样式设定p { color: red }类别作用于我们自行设定的类别&#xff0c;是使用频率最高的选择器.myClass { color: red }ID选取当前…

15JS06——流程控制-循环

目标&#xff1a; 1、循环 2、for循环 3、双重for循环 4、while循环 5、do while循环 6、continue break 7、命名规范以及语法格式 一、循环 1、循环的目的 可以重复执行某些代码 2、JS中的循环 for循环 while循环 do…while循环 二、for循环 在程序中&#xff0c;一…

机器学习 - 决策树

决策树是一种流程图&#xff0c;可以帮助我们根据以前的经验进行决策 比如&#xff0c;一个人将尝试决定他/她是否应该参加喜剧节目 下面是要用到的数据集 AgeExperienceRankNationalityGo36109UKNO42124USANO2346NNO5244USANO43218USAYES 读取并打印数据集 import pandas…

Transformer、Bert、Gpt对比系列,超详细介绍transformer的原理,bert和gpt的区别

一、Transformer架构图 Transformer 是一种用于序列到序列学习的神经网络模型&#xff0c;主要用于自然语言处理任务&#xff0c;如机器翻译、文本摘要等。它在2017年由 Google 提出&#xff0c;采用了注意力机制来对输入序列进行编码和解码。 Transformer 模型由编码器和解码…

随身WIFI折腾日记(五)---远程视频监控

六、远程视频监控 为了实现基于随身WIFI的网络摄像头&#xff0c;我参考了如下视频课程&#xff1a; 韦东山老师手把手带你从0开始自己做一个视频监控项目 系统由三部分组成&#xff1a;推流端(随身WIFI)、流媒体服务器(云服务器)、拉流端(浏览器/VLC播放器) 方案&#xff1…

NetworkInterface类

文章目录 1. 简介2. 工厂方法3. 获取方法 1. 简介 NetworkInterface类表示一个本地IP地址。这可以是一个物理接口&#xff0c;如额外的以太网卡&#xff08;常见于防火墙和路由器&#xff09;&#xff0c;也可以是一个虚拟接口&#xff0c;与机器的其它IP地址绑定到同个物理硬…

ensp实践dhcp服务

ensp实践dhcp服务 1、dhcp接口分配模式2、dhcp接口地址池分配模式3、dhcp布拉布拉布拉 1、dhcp接口分配模式 1.1、路由器AR1配置dhcp动态获取 <Huawei>system-view [Huawei]interface g0/0/0 [Huawei-GigabitEthernet0/0/0]ip address 10.1.1.1 24 [Huawei-GigabitEthe…

PixiJS 源码解读:绘制矩形,底层都做了什么?

大家好&#xff0c;我是前端西瓜哥&#xff0c;今天带大家看一下 PixiJS 的源码实现。 PixiJS 是一个非常流行的 Canvas 库&#xff0c;start 数将近 4w。 使用 PixiJS 简单易用的 API&#xff0c;我们可以在浏览器页面的 Canvas 元素上高性能地绘制图形&#xff0c;实现流畅…

基于深度学习的交通标志检测和识别(从原理到环境配置/代码运行)

项目是一个基于Python和OpenCV的交通标志检测和识别项目,旨在使用计算机视觉和深度学习技术对交通标志进行检测和分类。本文将从介绍项目原理和框架开始,详细介绍该项目的实现过程和技术细节,最后给出项目的安装和使用方法。 前后结果对比 识别前 识别后 一、 项目原理和框…

随身WIFI折腾日记(一)---霓虹灯

引言 通过对高通410芯片的随身WIFI刷写Debain系统&#xff0c;我们已经拥有了一台带4G功能的迷你ARM64单板电脑。现在我们可以基于此此平台进行一下二次开发。 随身WIFI的优势就是价格低廉&#xff0c;性能和树莓派zero2、树莓派3b差不多。 硬件配置如下&#xff1a; msm89…

随身WIFI折腾日记(二)---文件传输和软件安装

二、文件传输 我们可以通过SCP和SFTP工具和随身WIFI(USB连接)进行数据传输&#xff0c;上图以scp工具为例。 将本地电脑文件传输至随身WIFI&#xff0c;本地电脑上输入如下指令即可&#xff1a; scp /path/to/local/file user192.168.68.1:/path/to/remote/directory/注意&…

RK3568平台开发系列讲解(驱动基础篇)10min带你获取、了解与编译Kernel源代码

🚀返回专栏总目录 文章目录 一、Kernel获取二、Kernel根目录2.1 Documentation/2.1 arch/2.2 block/2.3 boot.its2.4 drivers/2.5 firmware/2.6 fs/2.7 include/2.8 init/2.9 ipc/2.10 kernel/2.11 lib/2.12 lo