序列化器的介绍和快速使用
drf提供了两个类:Serializer和ModelSerializer
之后我们只需要写自己的类,继承drf提供的序列化类,使用其中的方法就行
之后接口的编写我们可以使用APIView+序列化类+Response来完成
序列化类的基本使用--序列化多条
serializer.py--BookSerializer类(序列化类)
from rest_framework import serializers
class BookSerializer(serialiaer.Serializer):
name = serializers.CharField() # 大致与models下的类是对应的
price = serializers.CharField()
views.py--BookView类(视图类)
class BookView(APIView):
def get(self, request):
books = models.Book.objects.all()
# instance要序列化的数据,many=True则是用于queryset对象,如果是单个对象则不用传
ser = BookSerializer(instance=books, many=True)
# 无论是列表还是字典都可以被序列化
return Response(ser.data)
序列化单条数据
序列化类不动,视图类有改动
class BookDetailView(APIView):
def get(self, request, *args, **kwargs):
# 为了防止有多个参数使用可变长参数,所需参数从可变长参数中提取
book = models.Book.objects.filter(pk=kwargs.get('pk')).first()
ser = BookSerializer(instance=book)
return Response(ser.data)
反序列化
序列化类
1.新增
在序列化类中添加即可
def create(self, validated_data):
book = models.Book.objects.create(**validated_data)
return book
2.修改
def undate(self, instance, validated_data):
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.save()
return instance
视图类
1.新增
class BookView(APIView):
def post(self, request):
ser = BookSerializer(data=request.data) # 将前端传入的数据给data参数
# 校验数据
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
2.修改
class BookDetailView(APIView):
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(data=request.data, instance=book)
if ser.is_vaild():
ser.save()
return Response({'code':100, 'msg': '修改成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
反序列化的校验
在序列化类中添加钩子函数即可
1.局部钩子
def vaildata_name(self, name):
if 判断条件:
raise ValidationError('异常提示') # 校验不通过,抛异常
else:
return name
2.全局钩子
def validate(self, attrs):
if 判断条件:
raise ValidationError('异常提示')
else:
return attrs
序列化类常用字段和字段参数
常用字段
'''重要'''
1.CharField # 字符
2.IntegerField # 数字,整数
3.DecimalField # 数字,小数
4.DateTimeField # 时间,年月日时分秒
5.BooleanDield # 布尔值
6.ListField # 存列表
7.DictField # 存字典
8.SerializerMethodField # 用于定义数据的返回格式
'''了解'''
2.EmailField # 邮件
3.RegexField # 正则
5.URLField # 存URL
6.UUIDField # 存xxx-xxx-xxx格式数据
7.IPAddressField # 存IP地址
8.FloatField #
9.DurationField # 存时间戳
10.ChoiceField # 与django 中的choice相同
11.MultipleChoiceField # 多选
12.FileField # 文件
13.ImageField # 图片
常用段参数
1.CharField及其子类中使用的
max_length 最大长度
min_length 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
2.IntegerField中使用的
max_value 最大值
min_value 最小值
3.所有字段类都有的
read_only 表明该字段仅用于序列化输出,默认False(重点)
write_only 表明该字段仅用于反序列化输入,默认False(重点)
required 表明该字段在反序列化时必须输入,默认为True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认为False
validators 该字段使用的验证器
序列化高级用法之source
source也是一个字段参数,它的作用是修改传给前台的字段名,但是数据库中的字段名不变,即它可以定制字段名字
用法:用在序列化类中的
自有字段
real_name = serializer.CharField(max_length=8, source='name')
# 通过source关联数据库中的name字段,该字段的数据在前台展示时显示的字段名为real_name
关联字段,一对多,通过关联的表名点字段名
publish_name = serializer.CharField(source='publish.name')
# publish表中name字段的数据展示给前台显示的字段名为publish_name
source不能用于多对多的关联
序列化高级用法之定制字段的两种方式
SerializerMethodField定制
需求:
定制关联字段的显示形式
一对多的显示为字典
多对多的显示为列表套字典
class BookSerializer(serializers.Serializer):
name = serializers.CharField(max_length=8)
price = serializers.CharField()
# 定制返回格式
publish_detail = serializers.SerializerMethodField()
# SerializerMethodField方法必须搭配一个get方法使用,且get方法后面的名字必须与上面的变量名相同
def get_publish_detail(self, obj):
# 返回什么前台就展示什么
return {'name': obj.publish.name, 'addr': obj.publish.addr}
author_list = serializers.SerializerMethodField()
def get_author_list(self, obj):
l = []
for author in obj.authors.all():
l.append({'name': author.name, 'phone': author.phone})
return l
总结:
1.SerializerMethodField必须搭配一个方法使用
2.搭配的方法名必须为get_定制的字段名
3.搭配的方法返回什么,该字段在前台就展示什么
在表模型中定制
表模型中(models.py)
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.CharField(max_length=32)
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE) # 留住,还有很多
authors = models.ManyToManyField(to='Author')
@property # 伪装,将方法伪装成属性,在这里可以不写
def publish_detail(self):
# 返回什么前台就显示什么
return {'name': self.publish.name, 'addr': self.publish.addr}
@property
def author_list(self):
l = []
for author in self.authors.all():
l.append({'name': author.name, 'phone': author.phone})
return l
序列化类中
class BookSerializer(serializers.Serializer):
name = serializers.CharField(max_length=8)
price = serializers.CharField()
# 定义的字段类型需要与模型类中返回的数据类型一致
publish_detail = serializers.DictField() # 写在序列化类中的字段需要先在模型类中定义出来
author_list = serializers.ListField()
多表关联的反序列化保存
新增图书接口
前端传入的数据格式:{name:红楼梦,price:19,publish:1,authors:[1,2]} # publish和authors填写的是出版社主键值
视图类
class BookView(APIView):
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '新增成功'})
else:
return Response({'code': 101, 'msg': ser.errors})
序列化类
class BookSerializer(serializer.Serializer):
# name和price既要做序列化又要做反序列化,不用加read_only,write_only
name = serializer.CharField(max_length=8)
price = serializer.CharField()
# 只做序列化,加read_only
publish_detail = serializer.DictField(read_only=True)
author_list = serializer.ListField(read_only=True)
# 只做反序列化,加write_only
publish = serilizer.CharField(write_only=True)
authors = serializer.ListField(write_only=True)
# 新增要重写create方法
def create(self, validated_data):
book = models.Book.objects.create(name=validated_data.get('name'), price=validated_data.get('price'), publish_id=validated_data.get('publish'))
book.authors.add(*validated_data.get('authors'))
return book
修改图书接口
前端传入格式与新增图书相同
视图类:
class BookDetailView(APIView):
def put(self, request, pk):
book = models.Book.objects.filter(pk=pk).first()
ser = BookSerializer(data=request.data, instance=book)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功'})
else:
return Response({'code': 101, 'msg': ser.errors})
序列化类:
class BookSerializer(serializer.Serializer):
# name和price既要做序列化又要做反序列化,不用加read_only,write_only
name = serializer.CharField(max_length=8)
price = serializer.CharField()
# 只做反序列化,加write_only
publish = serilizer.CharField(write_only=True)
authors = serializer.ListField(write_only=True)
# 重写undate方法
def update(self, instance, validated_data):
# validated_data存储的是校验过后的数据
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.publish_id = validated_data.get('publish_id')
# authors是一个列表,需要先清空然后再添加
authors = validated_data.get('authors')
instance.authors.clear()
instance.authors.add(*authors)
instance.save()
return instance
ModelSerializer使用
ModelSerializer继承自Serializer它直接帮我们完成了一些操作
使用:
class BookSerializer(serializer.ModelSerializer):
class Meta:
model = Book # 与表建立关系
# fields = '__all__' # 直接序列化表中所有字段,也可以在列表中填写要序列化的字段,fields为固定写法
# 在Meta中写了fields,就相当于在这了复制了表模型中所有的字段
fields = ['name', 'price', 'public_detail', 'authors_list', 'publish', 'authors']
# 定制反序列化时给字段类加属性,也可以直接重写字段
extra_kwargs = {'name': {'max_length': 8},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True},
}