django restframework serializer 增加自定义字段操作
作者:NashCyk 发布时间:2023-12-17 20:36:10
在使用django restframework serializer 序列化在django中定义的model时,有时候我们需要额外在serializer中增加一些model中没有的字段。有两种方法实现这个目的。
假设现在有一个Animal模型,其中有name, type, country字段,country为外键。我们在序列化Animal时,需要额外增加外键country的area信息。
方法一修改数据库,利用model 这里就不多解释,主要来说第二种,不修改django的model,直接使用SerializerMethodField(method_name=None)字段。
class AnimalSerializer(serializers.ModelSerializer):
country_area = serializers.SerializerMethodField()
class Meta:
model = Animal
fields = ('id', 'name', 'type','country','country_area')
def get_country_area(self, obj):
return obj.country.area
SerializerMethodFiel是一个read-only字段
当不指定其method_name时,默认为get_field_name
如果使用ModelSerializer并指定字段时,要包含此时定义的字段
补充知识:django restframework Serializer field
SerializerMethodField
这是一个只读字段。它通过调用它所连接的序列化类的方法来获得它的值。它可用于将任何类型的数据添加到对象的序列化表示中。
签名: SerializerMethodField(method_name=None)
method_name - 要调用序列化对象的方法的名称。如果不包含,则默认为 get_<field_name>.
由 method_name 参数引用的序列化方法应该接受一个参数(除了 self),这是要序列化的对象。它应该返回你想要包含在对象的序列化表示中的任何内容。例如:
场景介绍:一个用户往往对应多个角色,而角色字段并不在UserProfile表中,这就需要我们新增角色字段到user序列化中
from .models import UserProfile
from .models import UserRole
class UserProfileSerializer(serializers.ModelSerializer):
"""
show list serializer
"""
role = serializers.SerializerMethodField()
class Meta:
model = UserProfile
# fields = "__all__"
fields = ["id", "username","role", "account", "really_name", "department", "tel_phone",
"create_time", "email", "last_time", "creator"]
def get_role(self,obj):
user_id = obj.id
roles = [i.role.name for i in UserRole.objects.filter(user_id=user_id)]
roles = ",".join(roles)
return roles
相反的场景:我们提交的表单数据存在于多表中(因为表中含有多对多字段),如何验证所有字段,并保存完整的数据到各表中。
刚开始的思路在ModelSerializer中新增未定义字段,然后发现这并不可行。我也犯了SerializerMethodField的错误,但随后去读了serializer的源码,以及了解serializer的顺序,就知道SerializerMethodField仅用于list方法。
问题的突破点到底在哪里呢,在drf serializer 官方文档中就有一个知识点,serializer.save(**kwargs),kwargs数据被绑定在serializer.validated_data对象上,当create或update的时候就会被添加进数据库,相当于validated_data.update(kwargs)
实际源码不是这样子,但也就是这么个意思。
重写Serializer create,update方法
from rest_framework.utils import model_meta
def create(self, validated_data):
field= validated_data.pop('field_name')
validated_data = validated_data
instance = Model.objects.create(**validated_data)
# ...外键表的操作
return instance
def update(self, instance, validated_data):
field= validated_data.pop('field_name')
info = model_meta.get_field_info(instance)
for attr, value in validated_data.items():
if attr in info.relations and info.relations[attr].to_many:
field = getattr(instance, attr)
field.set(value)
else:
setattr(instance, attr, value)
instance.save()
# ...
return instance
来源:https://blog.csdn.net/Nash_Cyk/article/details/79064245


猜你喜欢
- 本文介绍了使用XMlhttp技术来生成html页面,值得借鉴。相关函数:<% ’定义xmlhttp funct
- 一、演示效果b站:虎年烟花演示二、python代码import pygamefrom math import *from pygame.lo
- Function getIpvalue(clientIP)'得到客户端的IP转换成长整型,返回值getIpvalue&nb
- 本文实例讲述了Python生成8位随机字符串的方法。分享给大家供大家参考,具体如下:#!/usr/bin/env python# -*- c
- 基本映射映射使用在根据不同URLs请求来产生相对应的返回内容.Bottle使用route() 修饰器来实现映射.from bottle im
- 01. 应用场景及定义方式应用场景在实际开发中,对象 的 某些属性或方法 可能只希望 在对象的内部被使用,而 不希望在外部被访问到私有属性
- 前言:线性回归模型属于经典的统计学模型,该模型的应用场景是根据已知的变量(即自变量)来预测某个连续的数值变量(即因变量)。例如餐厅根据媒体的
- 效果图:基于d3-v5, 依赖dagre-d3, 直接上代码:<!DOCTYPE html><html lang=&quo
- 先看几个数据。。一大堆文字滴,不管人家是不是故意的,字数还是这样:news.163.cn:14px,39个中文字符 news.sina.co
- 本文实例讲述了python复制文件的方法。分享给大家供大家参考。具体分析如下:这里涉及Python复制文件在实际操作方案中的实际应用以及Py
- 先看下jupyter和pycharm环境的差别左边是jupyter-------------------------------------
- 问题起因最近要将一个文本分割成好几个topic,每个topic设计一个regressor,各regressor是相互独立的,最后汇总所有to
- 本文实例为大家分享了javascript实现倒计时提示框的具体代码,供大家参考,具体内容如下代码:<!DOCTYPE html>
- 环境:Python3.6.4 + pandas 0.22主要是DataFrame.apply函数的应用,如果设置axis参数为1则每次函数每
- Vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思想构建的。相比于Angular.js,Vue.js提
- 这里有一些很棒的自动化脚本,你可以在你的 Python 项目中使用它们。在做项目的时候,我们需要一些现成的代码来帮助我们解决日常生活中的问题
- 前言通常在读写文件之前,我们需要先判断文件或者目录是否存在。不然在接下来的处理中可能会报错。所以在做任何操作之前,最好还是先判断文件、目录是
- 基础类似于自定义指令,可以用全局方法 Vue.filter() 注册一个自定义过滤器,它接收两个参数:过滤器 ID 和过滤器函数。过滤器函数
- 前言利用Python的ffmpy库提取视频中的音频。本文提供工具类代码。环境依赖需要安装ffmpy,安装指令:pip install ffm
- 本文实例讲述了Python面向对象之静态属性、类方法与静态方法。分享给大家供大家参考,具体如下:1. 静态属性:在函数前加@property