一、自定义序列化组件
- 方法一:继承serializers.Serializer
class BookSerlizer(serializers.Serializer):
title = serializers.CharField()
price = serializers.IntegerField()
pub_date = serializers.DateField()
# source 可以指定一个字段也可以指定一个方法
publish = serializers.CharField(source='publish.name')
# 获取作者所有的信息,指定SerializerMethodField之后,可以对应一个方法,返回什么内容,authors就是什么内容
authors = serializers.SerializerMethodField(read_only=True)
# 对应的方法固定写法get_字段名
def get_authors(self, obj):
author_ser = AuthorSerlizer(obj.authors.all(), many=True)
return author_ser.data
- 方法二:继承serializers.ModelSerializer
class BookSerializer(serializers.ModelSerializer):
class Meta:
model=models.Book
# fields=('nid','name')
#不能跟fields同时使用
# exclude=['name',]
fields=('__all__')
#深度是1,官方建议不要超过10,个人建议不要超过3
# depth=1
authors=serializers.SerializerMethodField()
def get_authors(self,obj):
ret=AuthorSerializer(instance=obj.authors.all(),many=True)
return ret.data
name=serializers.CharField()
- 视图层
class Books(APIView):
def get(self, request):
back_dic = {
'code': 100,
'msg': '查询成功',
}
# 获取所有的图书数据
books = models.Book.objects.all()
# print(books)
# 序列化数据,many为True序列化多条数据,false序列化一条数据
# instance 序列化,data 反序列化
book_ser = BookSerlizer(instance=books, many=True)
# print(book_ser)
# 获取序列化后的数据
back_dic['data'] = book_ser.data
print(back_dic)
return Response(back_dic)
二、高级用法
1.source 的用法
- 可以指向字段
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
book_name = serializers.CharField(source='book')
price = serializers.CharField()
# 指向字段名
publish = serializers.CharField(source='publish.name')
- 可以指定方法
class BookSerializer(serializers.ModelSerializer):
# 指向方法
book_type =serializers.CharField(source='get_xx_display',read_only=True)
三、序列化总结
-序列化的两种方式
-Serializers:没有指定表模型
-source:指定要序列化哪个字段,可以是字段,可以是方法
- SerializerMethodField的用法
authors=serializers.SerializerMethodField()
def get_authors(self,obj):
ret=AuthorSerializer(instance=obj.authors.all(),many=True)
return ret.data
-ModelSerializers:指定了表模型
class Meta:
model=表模型
#要显示的字段
fields=('__all__')
fields=('id','name')
#要排除的字段
exclude=('name')
#深度控制
depth=1
-重写某个字段
在Meta外部,重写某些字段,方式同Serializers
四、反序列化
1、使用继承了Serializers序列化类的对象
- 序列化生成器中:自己重写create方法保存数据
def create(self, validated_data):
# print('1',validated_data)
publish = validated_data.pop('publish')
publish_obj = models.Publish.objects.filter(name=publish['name']).first()
# print(publish_obj)
validated_data['publish'] = publish_obj
res = models.Book.objects.create(**validated_data)
return res
- 视图层
def post(self, request):
back_dic = {
'code': 100,
'msg': '',
}
# 反序列化传入data
book_ser = BookSerlizer(data=request.data)
# print('1',request.data)
# 校验数是否合法
print(book_ser.is_valid())
# print(book_ser.errors)
if book_ser.is_valid():
print(book_ser.validated_data)
book_ser.create(book_ser.validated_data)
back_dic['data'] = book_ser.validated_data
back_dic['msg'] = '新增成功'
# print(back_dic)
return Response(back_dic)
2、使用继承了ModelSerializers序列化类的对象,反序列化
五、反序列化的校验——钩子函数
- 局部钩子
def validate_name(self,value):
print(value)
if value.startswith('sb'):
raise exceptions.ValidationError('不能以sb开头')
return value
- 全局钩子
def validate(self,attrs):
print(attrs)
if attrs.get('price')!=attrs.get('xx'):
raise exceptions.ValidationError('name和price相等,不正常')
return attrs
- 反序列化的校验
-validate_字段名(self,value):
-如果校验失败,抛出ValidationError(抛出的异常信息需要去bookser.errors中取)
-如果校验通过直接return value
-validate(self,attrs)
-attrs所有校验通过的数据,是个字典
-如果校验失败,抛出ValidationError
-如果校验通过直接return attrs