首页 > 其他分享 >重写DRF的to_representation和to_internal_value方法有什么用途?

重写DRF的to_representation和to_internal_value方法有什么用途?

时间:2024-05-06 17:36:57浏览次数:21  
标签:value internal representation 序列化 data class

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

to_representation() 允许我们改变序列化的输出。

to_internal_value() 允许改变我们反序列化的输出。

那么这两个方法该如何使用呢? 小编我今天就带你看一看!


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

from django.contrib.auth.models import User
from django.db import models


class Article(models.Model):
title = models.CharField(max_length=256)
body = models.TextField()
liked_by = models.ManyToManyField(to=User)


def __str__(self):
return self.title
每个文章资源有 title, body和 liked_by 三个字段。liked_by 代表喜欢该文章的用户对象id列表。

我们的序列化器ArticleSerializer类如下所示:

from rest_framework import serializers
from .models import Article


class ArticleSerializer(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方法。

from rest_framework import serializers
from .models import Article


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


def to_representation(self, value):
# 调用父类获取当前序列化数据,value代表每个对象实例obj
data = super().to_representation(value)
# 对序列化数据做修改,添加新的数据
data['total_likes'] = value.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提取我们所需要的数据,忽略不想要的数据。

from .models import Article
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'


def to_internal_value(self, data):
# 进提取所需要的数据,对其进行反序列化,data代表未验证的数据
article_data = data['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


# 定义好后,可以在序列化类中使用。
class DataPointSerializer(serializers.ModelSerializer):
coordinates = CoordinateField(source='*')


class Meta:
model = DataPoint
fields = ['label', 'coordinates']

小结
重写 to_representation() 和to_internal_value()方法不仅可以改变序列化数据的输出,处理反序列化的输入数据,还可以用来自定义字段。你都明白了吗?

原文链接:https://blog.csdn.net/weixin_42134789/article/details/115191672

标签:value,internal,representation,序列化,data,class
From: https://www.cnblogs.com/dreammooncy/p/18175476

相关文章

  • Oracle【ORA-00600 internal error code arguments [2662]】恢复一例
    背景1.数据库版本:11.2.0.42.未开启归档3.没有备份:无RMAN备份、无DUMP备份4.数据库redolog全部删除。解决思路:Oracle的隐含参数:_allow_resetlogs_corruption=TRUESYS>altersystemset"_allow_resetlogs_corruption"=truescope=spfile;数据库关闭数据库,在启动SQL......
  • 修改序列last_value 字段
    在PostgreSQL中,你不能直接更新序列(如seq_sys_config)的last_value字段,因为序列是一个特殊的系统对象,不允许你像普通表那样直接修改它的列。last_value实际上是序列的一个伪列,表示最后返回的值,但它不是一个可以直接设置的列。如果你想要修改序列的当前值或者重置它,你应该使用......
  • 解决报错:Could not set property 'id' of 'class com.north.domain.Book' with value
    报错原因问题描述:因为MyBatis-Plus默认的id自增策略使用的雪花算法org.mybatis.spring.MyBatisSystemException:nestedexceptionisorg.apache.ibatis.reflection.ReflectionException:Couldnotsetproperty'id'of'classcom.north.domain.Book'withvalue'1......
  • Text Representation
    1StatisticalModel1.1One-Hot1.2Bagofwords(BOW)https://web.stanford.edu/class/datasci112/lectures/lecture8.pdf1.3N-grams1.4TF-IDF2WordEmbedding(NeuralNetworkModel)2.1Word2Vechttps://projector.tensorflow.org/ContinuousBagofWords(CBOW......
  • WPF Slider Show integral value TickFrequency="1" IsSnapToTickEnabled="True"
    <Windowx:Class="WpfApp85.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.......
  • 问题解决:Failed to download metadata for repo ‘appstream‘: Cannot prepare inter
    大家都知道Centos8于2021年年底停止了服务,大家再在使用yum源安装时候,出现下面错误“错误:Failedtodownloadmetadataforrepo‘AppStream’:Cannotprepareinternalmirrorlist:NoURLsinmirrorlist”1、进入yum的repos目录代码语言:javascript复制cd/etc/yum......
  • SpringBoot+MyBatisPlus报错 Invalid value type for attribute 'factoryBeanObjectTy
    依赖版本org.springframework.boot:spring-boot-starter-web:3.2.5com.baomidou:mybatis-plus-boot-starter:3.5.5错误Invalidvaluetypeforattribute'factoryBeanObjectType'问题原因:这个问题是由于依赖传递导致,在MyBatis起步依赖中的myBatis-spring版本过低,导致程......
  • sql_mode=only_full_group_by以及ANY_VALUE()
    MySQL报错:sql_mode=only_full_group_by解决方法--查询自定义变量sql_modeSELECT@sql_mode;--查询系统变量sql_mode(会话变量)SELECT@@sql_mode;--查询当前会话变量SELECT@@SESSION.sql_mode;--查询全局变量select@@GLOBAL.sql_mode;SET@@SESSION.sql_mode='';......
  • centos8.2报错Failed to download metadata for repo 'BaseOS': Cannot prepare inter
    报错CentOS-8-Base68B/s|38B00:00错误:Failedtodownloadmetadataforrepo'BaseOS':......
  • dotnet 已知问题 错误标记 MethodImplOptions.InternalCall 特性参数将会在类型访问之
    本文将记录一个dotnet的已知问题。当自己不小心在方法上不正确标记了MethodImplAttribute特性时,错误选择了MethodImplOptions.InternalCall参数,那将会在运行的过程在,在此类型被访问之前就抛出了System.TypeLoadException异常,错误信息是Internalcallmethodwithnon_NUL......