【一】反序列化校验
1)三层校验
- 字段自己校验
- 直接写在字段类的属性上
- 局部钩子
- 在序列化中写
validata_字段名
- 在序列化中写
- 全局钩子
# serializers.py
class BookSerializer(serializers.Serializer):
# 1) name字段的要大于1小于10
name = serializers.CharField(min_length=1, max_length=10)
publish = serializers.CharField()
# 重建
def create(self, validated_data):
book = Book.objects.create(**validated_data)
return book
# 2) 局部钩子(针对name字段)
def validate_name(self, name):
if "sb" in name:
raise ValueError('书名中不能有sb')
else:
return name
# 3) 全局钩子
def validate(self, attrs):
name = attrs.get('name')
publish= attrs.get('publish')
if name == str(publish):
raise ValidationError('不能相同')
else:
return attrs
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from App.models import Book
from App.serializers import BookSerializer
class BookViewSet(APIView):
# 查询全部
def get(self, request):
books = Book.objects.all()
serializer = BookSerializer(instance=books, many=True)
return Response(serializer.data)
# 添加图书
def post(self, request):
serializer = BookSerializer(data=request.data)
### 若出错,停止代码,直接抛出异常
serializer.is_valid(raise_exception=True)
serializer.save()
return Response('ok', status=200)
【二】定制返回格式:source
1)定制表中某个字段
- 直接改名称,并在字段类的属性上添加
source='数据库的字段名'
# serializers.py
name = serializers.CharField()
# name改成book_name
book_name = serializers.CharField(source='name')
2)定制模型表
# 将指定字段输出的数据加是'_NB'
# models.py的指定库中
@property
def new_name(self):
return self.name + '_NB'
# serializers.py
name = serializers.CharField(source='new_name')
3)跨表查询
# 从Book表到publish表
publish= serializers.CharField(source='publish.name')
【三】定制返回格式:序列化
1)一对多关系
1.方式一:使用source
publish= serializers.CharField(source='publish.name')
2.方式二:在模型表中写
# 序列化类中(serializers.py)
# 字典格式用DecimalField,列表用ListField
publish_detail = serializers.DecimalField()
# 指定的模型表内(models.py)
def publish_detail(self):
return {'name': self.publish.name, 'addr': self.publish.addr}
3.方式三:在序列化类中写
publish = serializers.SerializerMethodField()
def get_publish(self, obj):
return {'name': obj.publish.name, 'addr': obj.publish.addr}
4.方式四:使用子序列化
# 在serializers.py内新写函数
class PublishSerializer(serializers.Serializer):
name = serializers.CharField()
addr = serializers.CharField()
# 序列化类中写入
publish = PublishSerializer()
2)多对多关系
- 与一对多相同
# 方式三示例
author = serializers.SerializerMethodField()
def get_author(self, obj):
authors = obj.author_book.all()
list_data = []
for author in authors:
list_data.append({'name': author.name, 'gender': author.get_gender_display()})
return list_data
【四】反序列化
- 通过在序列化类字段内添加参数实现判断
read_only=True
:只进行序列化操作write_only=True
:只进行反序列化操作
1)添加 - 示例
class BookViewSet(APIView):
def post(self, request):
serializer = BookSerializer(data=request.data)
# 若出错,停止代码,直接抛出异常
serializer.is_valid(raise_exception=True)
serializer.save()
return Response({'code': 200,'message': '添加成功','data': serializer.data})
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from App.models import Book, Author
class BookSerializer(serializers.Serializer):
name = serializers.CharField(min_length=1, max_length=10)
publish = serializers.SerializerMethodField(read_only=True)
def get_publish(self, obj):
return {'name': obj.publish.name, 'addr': obj.publish.addr}
author = serializers.SerializerMethodField(read_only=True)
def get_author(self, obj):
authors = obj.author_book.all()
list_data = []
for author in authors:
list_data.append({'name': author.name, 'gender': author.get_gender_display()})
return list_data
publish_id= serializers.IntegerField(write_only=True)
author_id = serializers.ListField(write_only=True)
# 重建create
def create(self, validated_data):
# 弹出author_id
author = validated_data.pop('author_id')
book = Book.objects.create(**validated_data)
book.author_book.add(*author)
return book
2)修改 - 示例
class BookDetailViewSet(APIView):
...
# 改
def put(self, request, pk):
book = Book.objects.get(pk=pk)
serializer = BookSerializer(instance=book, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response({'code': 200,'message': '添加成功','data': serializer.data})
# serializers.py内
class BookSerializer(serializers.Serializer):
...
# 重建update(旧,新)
def update(self, instance, validated_data):
# 弹出作者
author = validated_data.pop('author_id')
# 清除关系在添加
instance.author_book.clear()
instance.author_book.add(*author)
# 修改Book表
for key in validated_data:
setattr(instance, key, validated_data.get(key))
instance.save()
return instance
【五】ModelSerializer的使用
1)介绍
- ModelSerializer与模型表一一对应
- 可用不重写 create 和 update 便能进行添加修改
- 序列化与反序列化字段,可通过表映射
2)使用-示例
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model = Book
# 获取Book数据库中所有字段
# 包括关联的表(publish,author_book)
fields = '__all__'
# 获取指定字段
# fields = ['name', 'publish']
# 校验书写
extra_kwargs = {
'name': {'min_length': 1,'max_length': 10},
'publish': {'writer_only': True},
'author_book': {'writer_only': True},
}
# 局部钩子
def validate_name(self, name):
...
return name
# 全局钩子
def validate(self, attrs):
...
return attrs
3)定制返回格式-示例
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model = Book
# 获取指定字段
# 新增的需要注册才能使用
fields = ['name', 'publish_data','author_book_data']
# 校验书写
extra_kwargs = {
'name': {'min_length': 1, 'max_length': 10},
'publish_data': {'read_only': True},
'author_book_data': {'read_only': True},
}
publish_data = serializers.SerializerMethodField()
def get_publish_data(self, obj):
return {'name': obj.publish.name, 'addr': obj.publish.addr}
author_book_data = serializers.SerializerMethodField(read_only=True)
def get_author_book_data(self, obj):
authors = obj.author_book.all()
list_data = []
for author in authors:
list_data.append({'name': author.name, 'gender': author.get_gender_display()})
return list_data
标签:格式化,name,author,self,校验,ModelSerializer,publish,serializers,data
From: https://www.cnblogs.com/Mist-/p/18336157