DRF 序列化组件单增
自定义序列化(矬)
通常我们后端需要将数据查出来,并返回给需要数据的人,那么就产生了一个序列化的概念
我们可以自定义序列化并返回给客户端。
# 自定义序列化过程
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 序列化组件单增的更多相关文章
- 4)drf序列化组件 Serializer(偏底层)、ModelSerializer(重点)、ListModelSerializer(辅助群改)
知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 一.Serializer 偏底层 一般不用 理解原理 1.序列化准备 ...
- cvb源码分析,resful规范,drf,drf序列化组件,95
1 CBV的源码分析 -Class Base View(基于类的视图) -Function Base View(基于函数的视图) -def as_view 类方法 -def view:类方法内部,闭包 ...
- DRF 序列化组件
Serializers 序列化组件 Django的序列化方法 class BooksView(View): def get(self, request): book_list = Book.objec ...
- DRF 序列化组件 序列化的两种方式 反序列化 反序列化的校验
序列化组件 django自带的有序列化组件不过不可控不建议使用(了解) from django.core import serializers class Books(APIView): def ge ...
- DRF 序列化组件 模型层中参数补充
一. DRF序列化 django自带有序列化组件,但是相比rest_framework的序列化较差,所以这就不提django自带的序列化组件了. 首先rest_framework的序列化组件使用同fr ...
- DRF - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件
一.序列化组件 基于上篇随笔的表结构 , 通过序列化组件的ModelSerializer设计如下三个接口 : GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} ...
- drf序列化组件之视图家族
一.视图家族的分类 1.导入分类 from rest_framewok import views, generics, mixins, viewsets views:视图类 两大视图类:APIVi ...
- drf序列化组件
rest_framework序列化之Serializer 步骤: 1.自定义一个类,继承Serializer类: 2.在类中写要序列化的字段: 3.使用:在views.py文件中,book_ser=B ...
- DjangoRestFramework学习二之序列化组件、视图组件 serializer modelserializer
DjangoRestFramework学习二之序列化组件.视图组件 本节目录 一 序列化组件 二 视图组件 三 xxx 四 xxx 五 xxx 六 xxx 七 xxx 八 xxx 一 序列化组 ...
随机推荐
- IntelliJ IDEA 创建的文件自动生成 Author 注释 签名
IntelliJ IDEA 创建的文件自动生成 Author 注释 签名1.打开 File --> Setting2.找到 Editor --> File and Code Templat ...
- CSS3教程:Responsive框架常见的Media Queries片段
CSS3 Media Queries片段在这里主要分成三类:移动端.PC端以及一些常见的响应式框架的Media Queries片段.移动端Media Queries片段iPhone5@media sc ...
- Elasticsearch 搭建
最近需要用到Elasticsearch.下面简单介绍下Elasticsearch的搭建过程: ElasticSearch 使用java编写, 所以需要安装 Java 6以上 环境来运行. 并且确保设置 ...
- Landsat数据下载与介绍
1 数据下载 根据时间选择不同的Landsat卫星传感器 根据经纬度选择对应的条带: Lansdat Analysis Ready Data (ARD) Tile Conversion Tool: 把 ...
- 查看Linux 内核版本命令
1.Ubuntu 查看版本命令,三种方法. 1.使用 "uname -a" 2.使用 "lsb_release -a" 3.使用 "cat ...
- spring MVC 全局的异常处理
1.使用SimpleMappingExceptionResolver实现异常处理 在Spring的配置文件applicationContext.xml中增加以下内容: <bean class=& ...
- JS去重算法
1.遍历数组法 它是最简单的数组去重方法(indexOf方法) 实现思路:新建一个数组,遍历去要重的数组,当值不在新数组的时候(indexOf为-1)就加入该新数组中: var arr=[2,8,5, ...
- thinkphp rabc权限总结
今天晚上把ThinkPHP的权限分配弄明白了,心里的包袱立刻放下了,感觉那个爽啊!稍微记录一下. 背景:CMS系统开发(17do). 项目分组:Admin(后台管理).Home(前台显示). Admi ...
- 廖雪峰Java16函数式编程-2Stream-7其他操作
1. 排序 Stream<T> sorted(); //按元素默认大小排序(必须实现Comparable接口) Stream<T> sorted(Comparator<? ...
- 登录操作(方法二:for与else搭配)
登录操作(方法二:for与else搭配) user_name="star"passwoed='123' count=0for i in range(3): u_username=i ...