13、DRF实战总结:重写DRF的to_representation和to_internal_value方法的作用详解(附源码)

news2024/11/15 11:55:01

DRF的to_representation和to_internal_value是序列化和反序列化过程中最核心的方法,它们分别用于将数据对象转换成字典,和将字典转换成数据对象。

DRF所有序列化器类都继承了BaseSerializer类,通过重写该类的to_representation()和to_internal_value()方法可以改变序列化和反序列化的行为,比如给序列化后的数据添加额外的数据,或者对客户端API请求携带的数据进行反序列化处理以及用来自定义序列化器字段。

to_representation的作用是将查询集合、模型实例、JSON等数据类型,转换成DRF内置的Serializer所支持的数据类型(比如嵌套的Serializer、List、Dict等),从而可以对这些数据进行序列化。

to_internal_value的作用是将传入的字典数据(比如通过API POST提交的JSON数据),转换成需要保存到数据库的原生数据类型(比如序列化后需要保存到Model中的IntegerField、CharField等)。

重写这些方法的作用是可以自定义序列化和反序列化过程中的数据转换规则,从而可以满足各种不同的业务需求。比如可以根据不同的角色返回不同的数据、动态过滤掉某些字段、根据某些字段的取值计算生成额外的字段等。

  1. to_representation() 允许改变序列化的输出。
  2. to_internal_value() 允许改变反序列化的输出。

假设有如下一个文章模型(Article):

class Article2(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()
    like_by = models.ManyToManyField(to=User)

    def __str__(self):
        return self.title

每个文章资源有title, body和liked_by 三个字段。liked_by代表喜欢该文章的用户对象id列表。

序列化器ArticleSerializer类如下所示:

class ArticleSerializer8(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = '__all__'
 

如果使用上面序列化器去序列化单篇文章资源,将得到如下输出数据:

{
  "id": 1,
  "title": "DRF advanced tutorials",
  "body": "This is a good example.",
  "liked_by": [
    2,
    3,
    4
  ]
}

to_representation方法

如果希望给上面输出数据添加一个total_likes点赞总数的字段,只需要在序列化器类里重写to_representation方法。

class ArticleSerializer9(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = '__all__'

    def to_representation(self, instance):
        # 调用父类获取当前序列化数据,instance代表每个对象实例obj
        data = super().to_representation(instance)
        # 对序列化数据做修改,添加新的数据
        data['total_likes'] = instance.liked_by.count()
        return data

现在使用新的序列化器类去序列化单篇文章资源,将得到如下输出结果。to_representation() 方法改变了序列化的输出,并传递了额外的数据。

{
  "id": 1,
  "title": "DRF advanced tutorials",
  "body": "This is a good example.",
  "liked_by": [
    2,
    3,
    4
  ],
  "total_likes": 3
}

to_internal_value方法

to_internal_value主要在反序列化时用到,其作用处理API请求携带的数据,对其进行验证并转化为Python的数据类型。

假如API客户端通过请求提交了额外的数据,比如extra_info字段,如下所示

{
  "extra_info": {
    "msg": "Hello world!"
  },
  "article_data": {
    "id": 1,
    "title": "DRF advanced tutorials",
    "body": "This is a good example.",
    "liked_by": [
      2,
      3,
      4
    ],
    "total_likes": 3
  }
}

由于extra_info字段不属于ArticleSerializer类里的字段,如果直接使用ArticleSerializer类对上述数据进行反序列化会出现错误。

事实上反序列化时只需要提取article_data然后对其反序列化即可,所以可以重写to_internal_value提取所需要的数据,忽略不想要的数据。

class ArticleSerializer10(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = '__all__'

    def to_internal_value(self, data):
        # 提取所需要的数据,对其进行反序列化,data代表未验证的数据
        article_data = data.get('article_data', '')
        return super().to_internal_value(article_data)

自定义序列化器类字段

to_representation() 和to_internal_value()方法的另一个重要用途就是用来自定义序列化类字段。下例为DRF提供的一个官方演示,展示了如何使用这两个方法自定义了一个包含有x, y坐标的字段CoordinateField字段。

# 自定义序列化器类字段
class CoordinateField(serializers.Field):
    def to_representation(self, value):
        ret = {
            'x': value.x_coordinate,
            'y': value.y_coordinate
        }
        return ret

    def to_internal_value(self, data):
        ret = {
            'x_coordinate': data['x'],
            'y_coordinate': data['y']
        }
        return ret

定义好后,可以在序列化类中使用。

from .models import DataPoint
# 使用上述自定义序列化器类的字段
class DataPointSerializer(serializers.ModelSerializer):
    coordinates = CoordinateField(source='*')
    class Meta:
        model = DataPoint
        fields = ['label', 'coordiante']

输入才有输出,吸收才能吐纳。——码字不易

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

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

相关文章

Python ---->> PiP 的重要性

我的个人博客主页:如果’真能转义1️⃣说1️⃣的博客主页 关于Python基本语法学习---->可以参考我的这篇博客:《我在VScode学Python》 Python是一种跨平台的计算机程序设计语言,是一个高层次的结合了解释性、编译性、互动性和面向对象的语…

linux安装oracle

我系统为centos7,最小化安装的,需调用xshell图行化界面安装oracle** 前提准备 1、安装Xmanager,配置x11转发。 2、oracle下载地址 https://download.oracle.com 3、关闭selinux 临时关闭: setenforce 0 永久关闭 vim /et…

Servlet 和 Servlet API 简述

目录 1、什么是 Servlet? 2、Servlet API 有哪些内容? 3、Servlet 与 Tomcat 的区别和联系 4、常用的Web服务器有哪些? 5、拓展:Undertow 和Tomcat 的区别 1、什么是 Servlet? Servlet 是 Java Web 应用程序中的一…

使用 node 管理器管理 monorepo

使用 node 管理器管理 monorepo 不包含工具的使用,一方面因为我没用到过工具,另外一方面看了一下 Lerna,说 Learna 底层还是用到了 yarn 去进行管理,二者并不冲突,所以打算先学习一下基础再说。 顾名思义&#xff0c…

800V高压系统的驱动力和系统架构分析——为什么是800V高压系统,及其挑战?

摘要: 800V高压系统下汽车系统架构会出现哪些变化? 过去一年是新能源汽车市场爆发的一年,据中汽协数据,2021年新能源汽车销售352万辆,同比大幅增长157.5%。新能源汽车技术发展迅速,畅销车辆在动力性能、智…

IS210AEBIH3BED包含逻辑集成电路、存储器集成电路、专用集成电路

IS210AEBIH3BED包含逻辑集成电路、存储器集成电路、专用集成电路 什么是集成电路测试仪   集成电路测试仪是对集成电路进行测试的专用仪器设备。集成电路测试是保证集成电路性能、质量的关键手段之一。集成电路测试技术是发展集成电路产业的三大支撑技术之一,因此…

ELK部署

ELK部署 1. 整体部署规划1.1 服务器规划1.2 关闭防火墙,同步时间 2. ElasticSearch集群部署2.1 环境准备2.2 部署 Elasticsearch 软件 3. ELK Logstash 部署3.1 安装Logstash,httpd,java3.2 测试 Logstash与elasticsearch功能是否能做对接3.3 定义 logstash配置文件…

ES-IK分词器的概念和基本使用

文章目录 一、ES-IK分词器1.1 初识ES-IK分词器1.2 IK分词器-拓展和停用1.3 索引库1.3.1 mapping属性1.3.2 索引库的CRUD基本语法: 1.3.3 文档的DSL 一、ES-IK分词器 1.1 初识ES-IK分词器 ES IK分词器是一种基于中文文本的分词器,它是Elasticsearch中文分…

DJ4-4 网际协议:因特网中的转发和编址

目录 一、因特网中的网络层协议 二、IP 数据报格式(IPv4) 三、IP数据报分片和重组 1. 分片的概述 2. 分片的例子 四、IP 地址 1. IP 地址概述 2. IPv4 编址 3. IP 地址结构 4. 传统的 IP 地址分类 5. ABC 类地址 6. 特殊 IP 地址段 7. 特殊…

Mysql 截取字符串并将文本转换为数值

有一个需求, 需要在 字符串 20230410 中获取 月份(04), 然后变为 (4), 解决: SELECT cast(left(SUBSTRING(20230410, 5),2) as SIGNED); 用到的函数有 left(str, length) substring(str, pos),即:substring(被截取字符串, 从第几位开始截…

Linux驱动之在Ubuntu下编译驱动模块——学习笔记(12)

为了方便驱动开发学习,了解一下在Ubuntu上进行驱动编译的流程。 一、下载对应的内核源码 首先要通过 uname -a查询一下自己的内核版本。 我这里下载的是 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.tar.gz 二、编译内核 (1&a…

一起学 WebGL:复合矩阵

大家好,我是前端西瓜哥。之前讲了平移矩阵、旋转矩阵以及缩放矩阵,以及演示了在 WebGL 中的单独应用的效果。 这次我们看看同时进行多次矩阵变换的组合写法。 我们将会对一个三角形先平移,然后旋转。 矩阵乘法 简单过一下矩阵乘法的知识点…

Cassandra windos安装

首先从http://cassandra.apache.org/download/网站上找到cassandra,如下图所示: 2、点击3.11.3跳转到下载地址,如下图所示: …

DHCP服务器 DNS服务器 综合实验

配置DNS服务器 DNS服务器 主域服务器host1 192.168.80.101 从域服务器host2 192.168.80.102 DHCP服务器 host1 192.168.80.101 提供192.168.80.0/24网段 IP地址、默认网关、子网掩码、DNS服务器地址、DNS默认域名 客户端 Linux host3 19…

数据可视化神器!Matplotlib Python教程 | 从入门到精通绘制各种类型的图形和保存图形

大家好,我是爱吃熊掌的鱼,今天我要给大家带来一篇有趣开朗的Matplotlib Python教程。Matplotlib是Python中最流行的数据可视化库之一,它可以帮助我们将数据转化为易于理解的图表和图形。无论你是初学者还是专业人士,Matplotlib都是…

Eureka 注册中心——服务的注册与发现

文章目录 1.Eureka的结构和作用2.搭建eureka-server2.1.创建eureka-server服务2.2.引入eureka依赖2.3.编写启动类2.4.编写配置文件2.5.启动服务 3.服务注册3.1.引入依赖3.2 配置文件3.3启动多个user-service实例 4.服务发现4.1引入依赖4.2 配置文件4.3 服务拉取和负载均衡 最后…

flowable流程图绘制工具flowable-ui的安装和使用

一.简介 记录绘制flowable图的过程。 二.下载安装 1.下载 我这边是windows的,下载的版本是6.8.0,zip那个就可以,tar.gz是linux的 下载地址:https://github.com/flowable/flowable-engine/releases/tag/flowable-6.8.0 下载截…

PyCharm-2023安装教程

访问JetBrains的官方网站,下载PyCharm最新版本的安装程序。 双击下载的安装程序,在弹出的安装向导中点击“下一步”。 阅读许可协议,并同意协议条款。 选择安装路径。默认情况下,PyCharm会安装在C:\Program Files\JetBrain…

STL——Lambad表达式

📖作者介绍:22级树莓人(计算机专业),热爱编程<目前在c++阶段>——目标Windows,MySQL,Qt,数据结构与算法,Linux,多线程&…

【C语言】输入输出、字符串操作、内存操作、文件操作函数

三对基本输入输出函数 1.gets(),puts() gets()从标准输入中获取一个字符串,到str(自己创建的char型数组)中,读到换行或输入末尾结束获取r; 成功返回str,失败返回空。 char *gets(char *str)…