自定义序列化(矬)

通常我们后端需要将数据查出来,并返回给需要数据的人,那么就产生了一个序列化的概念

我们可以自定义序列化并返回给客户端。

# 自定义序列化过程
class UserV1View(APIView):
def get(self,request,*args,**kwargs):
pk = kwargs.get('pk')
if pk:
# 单查
user_dict = models.User.objects.filter(pk=pk,is_delete=False).values('username','img','sex').first()
if not user_dict:
return Response({'status':1,'msg':'geterror'},status=400)
user_dict['img'] = '%s%s%s' % (settings.BASE_URL,settings.MEDIA_URL,user_dict.get('img'))
return Response({'status':0,'msg':'ok','results':user_dict})
else:
# 群查
user_query = models.User.objects.filter(is_delete=False).all().values('username','img','sex')
user_dict = list(user_query)
for i in user_dict:
i['img'] = '%s%s%s' % (settings.BASE_URL,settings.MEDIA_URL,i.get('img'))
return Response({'status': 0, 'msg': 'ok', 'results': user_dict})

但是这种方式太过于复杂,如果字段多了,不好做拓展,那么我们可以使用DRF提供给我们的方法

Serializer类(方式繁琐)

底层序列化类 UserSerializer

  • 设置序列化字段,并且字段和类型必须和model模型类中一致
  • 如果不参与序列化的字段不写在 UserSerializer 类中
  • 自定义序列化字段,使用 serializers.SerializerMethodField()
api/serializers:
from rest_framework import serializers
from django.conf import settings
from api import models # 序列化:将数据从后端传给前端
class UserSerializer(serializers.Serializer):
# 序列化字段
username = serializers.CharField() # 自定义序列化字段
gender = serializers.SerializerMethodField()
# self:当前对象,obj参与序列化的models模型类对象
def get_gender(self,obj):
# 获取性别的映射
return obj.get_sex_display()
icon = serializers.SerializerMethodField()
def get_icon(self,obj):
return '%s%s%s' % (settings.BASE_URL, settings.MEDIA_URL,obj.img)

视图序列化步骤

视图CBV方式序列化过程:

  • 视图通过ORM操作得到数据对象
  • 将数据交给定义的序列化类UserSerializer序列化成返回给前台的数据
  • 返回序列化的数据给前台
# DRF 的 Serializer 序列化过程
from api import serializers
class UserV2View(APIView):
def get(self,request,*args,**kwargs):
pk = kwargs.get('pk')
if pk:
# 单查
user_obj = models.User.objects.filter(pk=pk, is_delete=False).first()
if not user_obj:
return Response({'status': 1, 'msg': 'geterror'}, status=400)
user_dict = serializers.UserSerializer(user_obj,many=False).data
return Response({'status': 0, 'msg': 'ok', 'results': user_dict})
else:
# 群查
user_query = models.User.objects.filter(is_delete=False).all()
user_dict = serializers.UserSerializer(user_query,many=True).data
return Response({'status': 0, 'msg': 'ok', 'results': user_dict})

底层反序列化类 UserCreatSerializer

  • 设置校验的字段,需与model模型类中的字段一致
  • 自定义校验字段和设置的系统校验字段定义没有区别,但是不需要入库(这字段参与全局钩子校验)
  • 所有字段可以设置对应局部钩子校验,校验成功返回value,失败抛异常
  • 所有字段可以设置对应全局钩子校验,校验成功返回attrs,失败抛异常
  • 重写create方法实现增入库,返回入库成功的对象
  • 重写update方法实现改入库,返回入库成功的对象
# 反序列化:将数据从前端传给后端
class UserCreatSerializer(serializers.Serializer):
# models模型类的字段
username = serializers.CharField(min_length=3,max_length=8,error_messages={
'min_length':'用户名太短',
'max_length':'用户名太长',
'required':'用户名不能为空',
}) password = serializers.CharField(min_length=3,max_length=8)
re_password = serializers.CharField(min_length=3,max_length=8)
# 不写就不参与序列化,写上就必须参与序列化
# required=False表示可写可不写。前台不提供,走默认值,前提是定义默认值
sex = serializers.BooleanField(required=False) # 局部钩子
# value:校验的字段数据
def validate_username(self,value):
if 'g' in value.lower():
raise serializers.ValidationError('名字中不能有g')
return value # 全局钩子
# attrs:所有校验的数据
def validate(self, attrs):
password = attrs.get('password')
re_password = attrs.pop('re_password')
if password != re_password:
raise serializers.ValidationError({'re_password':'两次密码不一致'})
return attrs # 在视图类中调用序列化类的save方法完成入库
# Serializer虽然有create方法,但具体没有实现,需要重写,因为不知道操作的是哪张表
def create(self, validated_data):
return models.User.objects.create(**validated_data) # instance表示要被修改的对象,validated_data代表校验后修改instance的数据
def update(self, instance, validated_data):
validated_data.pop('username')
models.User.objects.filter(pk=instance.id).update(**validated_data)
return instance

视图反序列化步骤

  • 从请求对象中获取前台携带的数据包参数
  • 交给反序列化类完成反序列化(data=request.data),实际上是数据的校验
  • 校验成功,借助反序列化类完成数据入库,返回前台入库成功的对象
    def post(self,request,*args,**kwargs):
user_obj = serializers.UserCreatSerializer(data=request.data)
if user_obj.is_valid():
# 入库
user_obj = user_obj.save()
return Response({'status':0,'msg':'ok','results':serializers.UserSerializer(user_obj).data})
else:
return Response({'status':1,'msg':user_obj.errors})

ModelSerializer类(重点)

序列化与反序列化类 UserModelSerializer

  • 序列化与反序列化类继承ModelSerializer类
  • 在配置类Meta中绑定序列化与反序列化相关的models模型表
  • fields配置,采用插拔式,设置所有参与序列化与反序列化字段
  • extra_kwargs配置,划分字段类型,区分是序列化还是反序列化
    • 序列化只读:read_only
    • 反序列化只写:write_only
    • 两者都可以可读可写:不写
  • 自定义序列化字段,提倡在models模型类中使用@property实现,可插拔
  • 自定义反序列化字段,同Serializer类设置字段即可,且可以在全局钩子校验,在extra_kwargs中设置的此字段类型无效,所以必须设置write_only=True
  • 可以对字段设置局部钩子或者全局钩子,同Serializer类
  • 不需要重写create和update方法,ModelSeializer类已提供

ModelSerializer 序列化类 比Serializer类高级,高级在我们不需要重写create和update方法,并且序列化和反序列化写在同一个类中,使用接口做序列化与反序列化区分就可以了。

# 序列化:将数据从后端传给前端
# 反序列化:将数据从前端传给后端
class UserModelSerializer(serializers.ModelSerializer):
# 自定义反序列化字段,需要声明write_only,在extra_kwargs中设置校验规则无效
re_password = serializers.CharField(min_length=3,max_length=8,write_only=True)
class Meta:
# 手动设置关联的model模型表
model = models.User
# 采用插拔式,设置所有参与序列化与反序列化字段
fields = ('username','gender','icon','sex','password','re_password')
extra_kwargs = {
# 不设置read_only或write_only,默认都参与。
'username':{
'min_length':3,
'max_length':8,
'error_messages':{
'min_length':'太短',
'max_length':'太长'
}
},
'icon':{'read_only':True},
'gender':{'read_only':True},
'password':{'write_only':True},
'sex':{'write_only':True}
} # 钩子函数同Serializer类中实现方式一样
def validated_username(self,value):
if 'g' in value.lower():
raise serializers.ValidationError('名字中不能含有g')
return value def validate(self, attrs):
password = attrs.get('password')
re_password = attrs.pop('re_password')
if password != re_password:
raise serializers.ValidationError({'re_password':'两次密码不一致'})
return attrs # create和update方法不需要再重写,ModelSeializer类已提供。

视图序列化与反序列化步骤

视图序列化使用的序列化与反序列化类都是同一个定义的UserModelSerializer类

序列化

  • 操作ORM查询数据,返回数据对象
  • 将返回的数据对象传入定义的UserModelSerializer类中,如果是单查,many=False,如果是群差,many=True,返回数据对象
  • 将数据使用Response返回给前台

反序列化

  • 获取请求携带的数据包参数
  • 传入定义的UserModelSerializer类中进行反序列化(data=request.data),实际上是数据的校验
  • 校验成功,借助反序列化类完成数据入库,返回前台入库成功的对象
# DRF 的 ModelSerializer 序列化与反序列化过程
class UserV3View(APIView):
# 单查群查
def get(self,request,*args,**kwargs):
pk = kwargs.get('pk')
if pk:
# 单查
user_obj = models.User.objects.filter(pk=pk, is_delete=False).first()
if not user_obj:
return Response({'status': 1, 'msg': 'geterror'}, status=400)
user_dict = serializers.UserModelSerializer(user_obj,many=False).data
return Response({'status': 0, 'msg': 'ok', 'results': user_dict})
else:
# 群查
user_query = models.User.objects.filter(is_delete=False).all()
user_dict = serializers.UserModelSerializer(user_query,many=True).data
return Response({'status': 0, 'msg': 'ok', 'results': user_dict}) def post(self,request,*args,**kwargs):
user_obj = serializers.UserModelSerializer(data=request.data)
if user_obj.is_valid():
# 入库
user_obj = user_obj.save()
return Response({'status':0,'msg':'ok','results':serializers.UserModelSerializer(user_obj).data})
else:
return Response({'status':1,'msg':user_obj.errors})

models模型类中自定义序列化字段

# 自定义序列化字段(插拔式,官方提倡使用)
@property
def gender(self):
return self.get_sex_display() @property
def icon(self):
from django.conf import settings
return '%s%s%s' % (settings.BASE_URL, settings.MEDIA_URL, self.img)

DRF 序列化组件单增的更多相关文章

  1. 4)drf序列化组件 Serializer(偏底层)、ModelSerializer(重点)、ListModelSerializer(辅助群改)

    知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 一.Serializer 偏底层 一般不用 理解原理 1.序列化准备 ...

  2. cvb源码分析,resful规范,drf,drf序列化组件,95

    1 CBV的源码分析 -Class Base View(基于类的视图) -Function Base View(基于函数的视图) -def as_view 类方法 -def view:类方法内部,闭包 ...

  3. DRF 序列化组件

    Serializers 序列化组件 Django的序列化方法 class BooksView(View): def get(self, request): book_list = Book.objec ...

  4. DRF 序列化组件 序列化的两种方式 反序列化 反序列化的校验

    序列化组件 django自带的有序列化组件不过不可控不建议使用(了解) from django.core import serializers class Books(APIView): def ge ...

  5. DRF 序列化组件 模型层中参数补充

    一. DRF序列化 django自带有序列化组件,但是相比rest_framework的序列化较差,所以这就不提django自带的序列化组件了. 首先rest_framework的序列化组件使用同fr ...

  6. DRF - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件

    一.序列化组件 基于上篇随笔的表结构 , 通过序列化组件的ModelSerializer设计如下三个接口 : GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} ...

  7. drf序列化组件之视图家族

    一.视图家族的分类 1.导入分类 from rest_framewok import views, generics, mixins, viewsets views:视图类 ​ 两大视图类:APIVi ...

  8. drf序列化组件

    rest_framework序列化之Serializer 步骤: 1.自定义一个类,继承Serializer类: 2.在类中写要序列化的字段: 3.使用:在views.py文件中,book_ser=B ...

  9. DjangoRestFramework学习二之序列化组件、视图组件 serializer modelserializer

      DjangoRestFramework学习二之序列化组件.视图组件   本节目录 一 序列化组件 二 视图组件 三 xxx 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 序列化组 ...

随机推荐

  1. KEIL, MDK 关于C99结构体变量初始化

    C99:here 例如声明了这样的结构体 void test1() { tt_t t1 ={ .a = , .d = 'd', .b = , .c = }; static tt_t t2 = { ,, ...

  2. 23-Ubuntu-文件和目录命令-查看文件内容-more 和 cat

    1. more---适合查看内容多的文件 格式: more 文件名 操作键 功能 空格键 显示手册页下一屏 Enter键 一次滚动手册页的一行 b 返回上一屏 f 前滚一屏 q 退出 例: more ...

  3. 【csp】2018-3

    第一题 跳一跳 题目: 题意:浅显.qwq 题解:2计数+1,到1就清空计数. 代码: #include<iostream> #include<cstdio> #include ...

  4. WPF datagrid AutoGenerateColumns隐藏部分列

    原文:WPF datagrid AutoGenerateColumns隐藏部分列 <DataGrid x:Name="gridWC" ItemsSource="{B ...

  5. 解决Keep-Alive 和 Close 不能使用此属性设置

    http://www.hejingzong.cn/blog/viewblog_86.aspx Keep-Alive 和 Close 不能使用此属性设置 public static void SetHe ...

  6. [转]nginx简易教程

    安装 nginx官网下载地址 发布版本分为 Linux 和 windows 版本. 也可以下载源码,编译后运行. 从源代码编译 Nginx 把源码解压缩之后,在终端里运行如下命令: $ ./confi ...

  7. 基于vue的环信基本实时通信功能

    本篇文章借鉴了一些资料,然后在这个基础上,我将环信的实现全部都集成在一个组件里面进行实现: https://blog.csdn.net/github_35631540/article/details/ ...

  8. rancher2.0 自定义应用商店(catalog)

    1.进入自定义应用商店页面 ===================================================== ================================ ...

  9. vue框架介绍

    vue框架介绍 一.vue 概念 vue 是一种开发用户界面的渐进式开发框架.渐进式指的是:你可以将vue作为一部分嵌入到web应用中,带来丰富的交互体验 二.vue特点及常见开发中的高级功能 1.解 ...

  10. Responder对象

    Responder对象 响应者是一个对象,它可以响应事件并处理它们.所有响应者对象是类的,最终从UIResponder的( IOS)或NSResponder ( OS X)继承实例.这些类声明一个编程 ...