自定义序列化(矬)

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

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

# 自定义序列化过程
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. 一幅图解决R语言绘制图例的各种问题

    一幅图解决R语言绘制图例的各种问题 用R语言画图的小伙伴们有木有这样的感受,"命令写的很完整,运行没有报错,可图例藏哪去了?""图画的很美,怎么总是图例不协调?" ...

  2. JVM内核-原理、诊断与优化学习笔记(一):初识JVM

    文章目录 JVM的概念 JVM是Java Virtual Machine的简称.意为Java虚拟机 虚拟机 有哪些虚拟机 VMWare或者Visual Box都是使用软件模拟物理CPU的指令集 JVM ...

  3. MPU-6000 与 MPU-6050

    VLOGIC 是什么呢?

  4. OSI七层网络模型分别是哪七层?各运行那些协议?

    本文摘自:https://blog.csdn.net/JeremyZJM/article/details/78184775 应用层 DHCP · DNS · FTP · Gopher · HTTP · ...

  5. 面向XX程序设计到底是个啥

    面向过程编程:面向(对着)-->过程(流程步骤)-->编程(码代码) IPO是啥 input(输入)-->process(过程处理)-->output(输出) 未来码代码的目的 ...

  6. mysql UDF提权 sys_bineval

    介绍: 执行shellcode – sys_bineval sqmapl自带udf.dll中存在函数’sys_bineval,执行shellcode – sys_bineval 利用: MSF生成sh ...

  7. Laravel 迁移检查表是否存在

    Schema::hasTable('TableName'); //检查表释放存在 Schema::hasColumn('tableName', 'columeName'); //检查表是否存在某个字段 ...

  8. CSIC_716_20191102【input、数据类型概述、运算符】

    1.与用户交互 python2和python3在与用户交互方面存在差异. 在python3中,使用input( )方法提供用户输入,而在python2中,使用raw_input( )方法,才能实现同样 ...

  9. js实现点击空白处隐藏

    部分业务要求除了某元素外点击其他对象,对应的元素隐藏,下面是一个demo效果, <!DOCTYPE html> <html> <head> <meta cha ...

  10. Python自学:第五章 使用函数range( )

    # -*- coding: GBK -*- for value in range(1,5): print(value) 输出为: 1 2 3 4