drf框架中的Serializer序列化组件
03-01 Serializer组件
1.定义序列化器
在Django REST framework中如果想为某个模型类提供一个序列化器,需要自定义一个类,然后继承rest_framework.serializers.Serializer。
序列化类:
# serializers.py
from rest_framework import serializers
# 序列化类
class UserSerializer(serializers.Serializer):
# 注意:参与序列化的字段必须跟模型类中的字段同名
name = serializers.CharField()
age = serializers.IntegerField()
# DecimalField字段需要提供如下两个参数
height = serializers.DecimalField(max_digits=5, decimal_places=2)
# 自定义序列化字段,序列化的属性值由方法来提供,
# 方法的名字:固定为get_属性名,
# 方法的参数:(系列化对象, 序列化的model对象)
# 自定义序列化字段名不要和model中已有的属性重名
gender = serializers.SerializerMethodField()
def get_gender(self, obj):
return obj.get_sex_display
反序列化类:
# serializers.py
# 反序列化类
class UserDeserializer(serializers.Serializer):
# 反序列化属性名不是必须与model属性名对应,但是与之对应会方便序列化将校验通过的数据与数据库进行交互
name = serializers.CharField(min_length=3, max_length=6, errormessages={
'required': '姓名不能为空',
'min_length': '姓名不能少于3位'
})
...
# 系统可选的反序列化字段:没有提供不进行校验(数据库中有默认值或者可以为空),提供了就进行校验
age = serializers.IntegerField(min_value=0, max_value=100, requied=False)
# 自定义反序列化字段:一定参与校验,且要在校验过程中,将其从入库的数据中取出,剩余与model对应的数据才会入库
re_pwd = serializers.CharField(min_length=3, max_length=11)
# 自定义校验规则:局部钩子,全局钩子
# 局部钩子:validate_字段名(self, 字段值)
# 规则:成功返回value,失败抛异常
def validate_name(self, value):
if '#' in value:
raise serializers.ValidationError('名字含有非法字符')
return value
# 全局钩子:validate(self, 所有校验的数据字典)
# 规则:成功返回attrs, 失败抛异常
def validate(self, attrs):
# 取出联合校验的字段们:不需要入库的从校验字段中取出
pwd = attrs.get('pwd')
# 从attrs中移除re_pwd,方便剩余数据入库
re_pwd = attrs.pop('re_pwd')
if pwd != re_pwd:
raise serializers.ValidationError({'re_pwd': '两次密码不一致'})
return attrs
# 添加数据需要重写create方法
from . import models
def create(self, validated_data):
return models.User.objects.create(**validated_data)
视图类使用序列化类序列化数据:
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from . import models, serializers
class UserAPIView(APIView):
# 单查群查
def get(self, request, *args, **kwargs):
"""
1. ORM操作数据库拿到资源数据
2. 格式化成能够返回给前台的数据(序列化)
3. 返回格式化后的数据给前台
"""
pk = kwargs.get('pk')
if pk:
user_obj = models.User.objects.filter(pk=pk).first()
if notuser_obj:
return Response({'status': 1, 'msg': 'error'})
# 完成序列化
user_ser = serializers.UserSerializer(user_obj)
user_data = user_ser.data
return Response({
'status': 0, 'msg': '单查 ok',
'results': user_data,
})
# 群查
user_query = models.User.objects.all()
# 完成序列化,当传入多个对象的时候需要指定参数many=True
user_list_data = serialiazers.UserSerializer(user_query, many=True)
return Response({
'status': 0, 'msg': '群查 ok',
'results': user_list_data
})
视图类使用反序列化类反序列化数据:
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from . import models, serializers
class UserAPIView(APIView):
# 单增
def post(self, request, *args, **kwargs):
"""
1. 从请求对象中拿到前台的数据
2. 校验前台数据是否合法
3. 反序列化成后台Model对象与数据库交互
"""
request_data = request.data
# 反序列化的目的:封装数据的校验过程,以及与数据库交互的过程
# 注意:反序列化需要将数据传给data参数
user_ser = serializers.UserDeserializer(data=request_data)
# 调用反序列化的校验规则:系统规则,自定义规则(局部钩子,全局钩子)
# 这里类似Django的forms组件中的is_valid()方法
result = user_ser.is_valid()
if result:
# 校验通过,与数据库进行交互: 增(create),改(update)
user_obj = user_ser.save()
return Response({
'status': 0, 'msg': 'OK',
# 调用序列化类,将新建的对象序列化并返回给前端
'results': serializers.UserSerializer(user_obj).data
})
else:
# 校验失败, 返回错误信息
return Response({
'status': 1,
'msg': user_ser.errors
}, status=400)
2.总结
序列化:
"""
一、视图类的三步操作
1. ORM操作数据库拿到资源数据
2. 格式化(序列化)成能够返回给前端的数据类型
3. 返回格式化后的数据给前端
二、视图类的序列化操作
1. 直接将要序列化的数据传给序列化类
2. 要序列化的数据如果是单个对象,序列化的参数many为False,如果是多个,many为True
三、序列化类
1. model类中要返回给前台的字段,在序列化类中要进行声明,属性名必须与model的字段名相同,且Field类型也要保持一致
2. model类中不需要返回给前台的字段,在序列化类中不需要声明(省略)
3. 自定义序列化字段用SerializerMethodField()作为字段类型,该字段的值来源于 get_自定义字段命(self, obj)方法的返回值
"""
反序列化:
"""
一、视图类的三步操作
1. 从请求对象中拿到前台的数据
2. 校验前台的数据是否合法
3. 反序列化成后台Model对象与数据库交互
二、视图类的反序列化操作
1. 将要反序列化的数据传给反序列化类的data参数
2. 要反序列化的数据如果是个单个字典,反序列化类的参数many=False,多个many=True
三、反序列化类
1. 系统的字段,可以在Field类型中设置系统校验规则(name=serializers.CharField(min_length=3))
2. required校验规则决定该字段是否需要校验(默认required为True,数据库字段有默认值或可以为空的字段required可以赋值为False,不写不校验)
3. 自定义的反序列化字段,设置系统校验规则同系统字段,但需要在自定义校验规则中(局部、全局钩子)将自定义反序列化字段取出(返回剩余的数据与数据库交互)
4. 局部钩子的方法命名:validate_属性名(self, value) 失败抛异常,成功返回value
5. 全局钩子的方法命名:validate(self, attrs) 失败抛异常,成功返回attrs
"""