今日内容概要
- 序列化类常用字段和字段参数
- 序列化高级用法之source
- 序列化高级用法之定制字段的两种方式
- 多表关联反序列化保存
- 反序列化字段校验其他
- ModelSerializer使用
今日内容详细
序列化类常用字段和字段参数
序列化类中的字段类和模型层中的字段类型类似 并且也可以传参数
具体看图
需要记住的主要有:
CharField 字符串字段
IntegerField 整型字段
DecimalField 浮点型字段
DateTimeField 时间字段
BooleanField 布尔字段
以及序列化类中独有的字段
ListField
DictField
字段参数:
1.CharField及其子类的参数---->反序列化的校验 字段自己的规则
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
2.IntegerField的参数
max_value 最小值
min_value 最大值
3.所有字段类都有的参数
required 表明该字段在反序列化时必须输入 默认True
default 反序列化时使用的默认值
allow_null 表名该字段是否允许传入None 默认False
validators 该字段使用的验证器
----了解即可----
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面时 显示的字段名称
help_text 用于HTML展示API页面时 显示的字段帮助提示信息
----序列化类中的重点----
read_only 表明该字段仅用于序列化输出 默认False
write_only 表明该字段仅用于反序列化输入 默认False
反序列化校验执行流程
1.先执行字段自己的校验规则 如最大长度 最短长度等等
2.validators中的校验规则
如: name = serializers.CharField(validators=[函数名,])
3.局部钩子校验规则
4.全局钩子校验规则
序列化高级用法之source
先创建表
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)
author = models.ManyToManyField(to='Author')
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
class Author(models.Model):
name = models.CharField(max_length=32)
phone = models.CharField(max_length=11)
source可以指定序列化字段的名字
class BookSerializer(serializers.Serializer):
# 字段参数 通用的,所有字段都可以写 通过source指定哪个字段
# 自有字段 直接写字段名字
name_real = serializers.CharField(max_length=8, source='name')
real_price = serializers.CharField(source='price')
# 关联字段 一对多的关联,直接点
publish = serializers.CharField(source='publish.name')
#多对多 source不能用 无法直接取到所需的数据
authors=serializers.CharField(source='authors.all')
序列化高级用法之定制字段的两种方式
'''方式一: 使用SerializerMethodField定制'''
可以定制关联字段的显示形式
class BookSerializer(serializers.Serializer):
name = serializers.CharField(max_length=8)
price = serializers.CharField()
# 定义一个字段 使用SerializerMethodField
publish_detail = serializers.SerializerMethodField()
# 定义一个函数 函数名必须是 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):
# 多对多的表关系返回一个列表套字典
return [{'name': author.name, 'phone': author.phone}for author in obj.author.all()]
'''方式二: 在表模型中定制'''
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)
author = models.ManyToManyField(to='Author')
# 函数名与序列化类中的字段名一致
def publish_detail(self):
return {'name': self.publish.name, 'addr': self.publish.addr}
# 函数名与序列化类中的字段名一致
def author_list(self):
return [{'name': author.name, 'phone': author.phone} for author in self.author.all()]
序列化类中
class BookSerializer(serializers.Serializer):
name = serializers.CharField(max_length=8)
price = serializers.CharField()
# 字典使用DictField字段 字段名与模型层中的函数名一致
publish_detail = serializers.DictField()
# 列表使用ListField字段 字段名与模型层中的函数名一致
author_list = serializers.ListField()
多表关联反序列化保存
'''新增一个创建图书接口'''
--前端传入的数据格式: {name:红楼梦,price:19,publish:1,authors:[1,2]}
视图类
class BookView(APIView):
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '新增成功'})
return Response({'code': 101, 'msg': ser.errors})
序列化类
class BookSerializer(serializers.Serializer):
# name和price字段既用来序列化也用来反序列化
name = serializers.CharField()
price = serializers.CharField()
# publish_detail和author_list只用来做序列化 所以添加一个字段参数read_only=True
publish_detail = serializers.DictField(read_only=True)
author_list = serializers.ListField(read_only=True)
# 新增两个反序列化字段 并且是只写的 添加字段参数write_only=True
# 书只能有一个出版社 所以前端传过来的只有一个 无需用字典字段
publish = serializers.CharField(write_only=True)
author = serializers.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'))
# 多对多第三张表是自动创建的 可以使用add方法将传入的作者打散写入到第三张表中
book.author.add(*validated_data.get('author'))
return book
'''修改图书接口'''
视图类
class BookDetail(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': '修改成功'})
return Response({'code': 101, 'msg': ser.errors})
序列化类
class BookSerializer(serializers.Serializer):
def update(self, instance, validated_data):
# 可以使用for循环 也可以一条条取出修改
for new, params in validated_data.items():
if new == 'publish':
new += '_id'
elif new == 'author':
# 可以先将原本的关系清空再add添加
instance.author.clear()
instance.author.add(*params)
continue
# 利用反射来修改
setattr(instance, new, params)
instance.save()
return instance
反序列化字段校验其他
总共四层
1.字段自己的 如: name = serializer.CharField(max_length=8)
2.validators=[方法,]
3.局部钩子
4.全局钩子
ModelSerializer的使用
ModelSerializer继承自Serializer 帮我们节省了很多的操作
使用它的话序列化类和表模型是强关联的 只能序列化指定表
并且大部分请求都不需要手动写create和update方法了
固定写法
class 序列化类名(serializer.ModelSerializer):
class Meta:
model = 关联的表模型
fields = [序列化的字段,...] # '__all__'表示序列化表中所有的字段
# 当需要定制反序列化的字段时 可以在extra_kwargs中添加字段属性 或者重写 与Meta类同级
extra_kwargs = {字段名:{字段属性:值},...}
# 局部钩子和全局钩子的使用方法和之前一致
举例:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = models.Book
fields = ['name', 'price', 'publish_detail', 'author_list', 'publish', 'author']
extra_kwargs = {'name': {'max_length': 8},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
'publish': {'write_only': True},
'author': {'write_only': True}}
def validate_name(self, name):
if name.startswith('鸡'):
raise ValidationError('不能鸡开头')
return name
标签:serializers,name,author,publish,CharField,drf4,序列化
From: https://www.cnblogs.com/lzjjjj/p/17087195.html