创建序列化类字段参数
from rest_framework import serializers
from app01.models import Book
举例:
class BooksSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.IntegerField()
emial = serializers.EmailField()
publish_dict = serializers.DictField(read_only=True)
authors_list = serializers.ListField(read_only=True)
publish = serializers.CharField(write_only=True)
authors = serializers.ListField(write_only=True)
常用字段可设置参数:
CharField: 字符串
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
IntegerField: 数字整型
max_value 最大值
min_value 最小值
所有字段通用设置:
read_only 表明该字段仅用于序列化输出, 默认False 仅在读取数据是生效
write_only 表明该字段仅用于反序列化输入,默认False 仅在新增数据时生效
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值 存入数据时字段默认值
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
了解一下:
error_messages 包含错误编号与错误信息的字典
label 用于HTML展示API页面时,显示的字段名称
help_text 用于HTML展示API页面时,显示的字段帮助提示信息
写入数据反序列化校验流程
1.先效验字段参数设置校验,
2.validators设置的方法
3.局部钩子
4.全局钩子
序列化类字段名展示修改source
# 重点:source可以指定序列化字段的名字
-自有字段,直接写字段名字
-name_real = serializers.CharField(max_length=8, source='name')
-关联字段,一对多的关联,直接点
-publish = serializers.CharField(source='publish.name')
-多对多,搞不了,source不能用
-authors=serializers.CharField(source='authors.all')
这样可以隐藏数据库字段名
name_real = serializers.CharField(source='name')
前端收到的是name_real字段数据,但数据其实还是数据库里面的name字段
序列化之获取数据-read
序列化之高级获取定制字段类型:
方法1:在序列化类中使用 .SerializerMethodField()方法
模型类不用改,相当于把获取到的数据到这里二次加工后返回给前端
# 定制关联字段的显示形式
-一对多的,显示字典
-多对多,显示列表套字典
class BookSerializer(serializers.Serializer):
name = serializers.CharField(max_length=8)
price = serializers.CharField()
publish_detail = serializers.SerializerMethodField()
# publish_detail字段需要直接给前端返回所有的信息,已字典的形式
# 所以可以是用.SerializerMethodField()方法,搭配def get_publish_detail
# 让这个字段返回的是我们自定义de
def get_publish_detail(self, obj):
# get_名字一定要跟上面的一直
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
方法2:models模型类中编写方法(推荐)
序列化类只需要更改一下接受的数据类型即可
直接在模型类中 编写方法
class Book(models.Model):
name = models.CharField(max_length=12)
price = models.CharField(max_length=10)
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Authors')
@property
def publish_dict(self):
# 编写方法 直接将需要的数据格式返回
return {'name': self.publish.name, 'addr': self.publish.address}
@property
def authors_list(self):
# 编写方法 直接将需要的数据格式返回
l1 = []
for author in self.authors.all():
l1.append({'name': author.name, 'addr': author.address})
return l1
序列化类中:
class BooksSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.CharField()
publish_dict = serializers.DictField(read_only=True)
# read_only=True只有序列化时执行
# 这里的变量名对应模型类中的方法
# 接受的数据类型对象模型类中返回的数据类型 字典类型
authors_list = serializers.ListField(read_only=True)
# 这里的变量名对应模型类中的方法
# 接受的数据类型对象模型类中返回的数据类型 列表类型
这样前端得到的就是:
{
"code": 100,
"msg": "获取成功",
"result": [
{
"name": "完美世界",
"price": "122",
"publish_dict": {
"name": "完美出版社",
"address": "北京"
},
"authors_list": [
{
"name": "吴彦祖",
"phone": "18838228881"
},
{
"name": "张无忌",
"phone": "18838228881"
}
]
}
]
}
反序列化之新增数据 -write
前端传入数据格式,json :{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': '新增成功'})
else:
return Response({'code': 101, 'msg': ser.errors})
def delete(self, request, id):
Books = Book.objects.filter(pk=id).first()
Books.authors.clear()
Books.delete()
return Response({'msg': '删除成功'})
# 序列化中中需要改变代码
class BookSerializer(serializers.Serializer):
name = serializers.CharField(max_length=8)
price = serializers.CharField()
# 只用来做序列化 只读 read_only
publish_detail = serializers.DictField(read_only=True)
author_list = serializers.ListField(read_only=True)
# 只用来做反序列化 只写 write_only
publish = serializers.CharField(write_only=True)
authors = serializers.ListField(write_only=True)
# 根据前端传入的数据类型来设置,由于authors字段前端传入的是一个列表,所以我们也使用列表接收
def create(self, validated_data):
# 新增数据需要些create方法
book = Book.objects.create(name=validated_data.get('name'), price=validated_data.get('price'),
publish_id=validated_data.get('publish'))
# 创建一个book对象 字段数据都从validated_data中取
# publish_id外键字段
book.authors.add(*validated_data.get('authors'))
# book.author多对多关系的第三章表,由于是自动创建的,可以使用add方法
# validated_data.get('authors') = [1,2]
# *validated_data.get('authors')使用一个*语法将列表打散 传入了add方法中
return book
反序列化之修改数据
-前端传入的数据格式:{name:红楼梦,price:19,publish:1,authors:[1,2]}
新增一个路由地址 传送url接收id
class BookDetailView(APIView):
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(data=request.data, instance=book)
# instance=book 需要修改的对象,data=request.data,前端传入的数据
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功'})
else:
return Response({'code': 101, 'msg': ser.errors})
序列化类中:重写update方法
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')
# 关于第三张表
instance.authors.clear()
# 先清空第三章表关系
instance.authors.add(*validated_data.get('authors'))
# 然后再重新添加第三章表关系
instance.save()
return instance
反序列化时字段校验
class BooksSerializer(serializers.Serializer):
name = serializers.CharField(max_length=6,min_length=3,allow_blank=False,error_messages={
'max_length':'太长了',
'min_length':'太短了',
'allow_blank':'不能为空'
})
def validate_name(self, name):
if name == 'moon':
raise ValidationError('不可以叫这个')
else:
return name
# 可以使用字段参数限制,也可以使用钩子函数限制
最方便的ModelSerializer使用
ModelSerializer可以帮助我们快速实现 序列化反序列化接口
# 视图类函数 无需更改:
class BooksView(APIView):
def get(self, request):
books = Book.objects.all()
ser = BookSerializer(instance=books, many=True)
return Response({'code': 100, 'msg': '获取成功', 'result': ser.data})
def post(self, request):
book_obj = BookSerializer(data=request.data)
if book_obj.is_valid():
book_obj.save()
return Response({'code': 100, 'msg': '新增成功', 'result': book_obj.data})
else:
return Response({'code': 101, 'msg': book_obj.errors})
# 序列化类中 需要继承ModelSerializer
from rest_framework import serializers
from .models import Book
from rest_framework.serializers import ValidationError
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
#该 序列化类关联的表格
fields = ['id', 'name', 'price', 'publish_dict', 'authors_list', 'publish', 'authors']
# 设置需要展示表字段内容
# 方式一:字段添加约束条件,控制字段读写方式
extra_kwargs = {'publish': {'write_only': True},
'authors': {'write_only': True},
'publish_dict': {'read_only': True},
'authors_list': {'read_only': True}}
# 一定在写在class Meta:类外面
name = serializers.CharField(max_length=4, error_messages={'max_length': '太长了'})
# 方式二:也是给序列化字段添加约束条件,改相当于重写了字段要求 一定要写在类外面
publish_dict = serializers.SerializerMethodField()
# 构建字段返回内容
def get_publish_dict(self, obj):
return {'name': obj.publish.name, 'addr': obj.publish.address}
author_list = serializers.SerializerMethodField(read_only=True)
# 构建字段返回内容
def get_author_list(self, obj):
l = []
for i in obj.authors.all():
l.append({'name': i.name, 'phone': i.address})
return l
# 钩子函数
def validate_name(self, name):
if name.startswith('sb'):
raise ValidationError('不能sb')
else:
return name
# 这样就完成了 接口 读 新增 修改
# 删除不涉及序列化 直接在视图类中写即可
标签:serializers,name,publish,接口,authors,编写,序列化,data,drf
From: https://www.cnblogs.com/moongodnnn/p/17087448.html