序列化组件
序列化之Serializers
序列化
models部分
from django.db import models
# Create your models here.
class Book(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
publish_date = models.DateField(null=True)
xx=models.IntegerField(choices=((0,'文学类'),(1,'情感类')),default=1,null=True)
publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE,null=True)
authors=models.ManyToManyField(to='Author')
def __str__(self):
return self.name
def test(self):
return 'xxx'
class Author(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField()
def __str__(self):
return self.name
在app01下新建一个py文件,这里命名为app01serilaizer
app01serializer部分
from app01 import models
from rest_framework import serializers
class AuthorSerializer(serializers.Serializer):
name=serializers.CharField()
age=serializers.CharField()
class BookSerializer(serializers.Serializer):
#指定source='name' ,表示序列化模型表中的name字段,重名命为name5(name和source='name'指定的name不能重名)
name5=serializers.CharField(source='name')
# #write_only 序列化的时候,该字段不显示
# #read_only 反序列化的时候,该字段不传
price=serializers.CharField(write_only=True)
# #如果要取 出版社的city source='publish.city'
publish=serializers.CharField(source='publish.name')
# #source不但可以指定一个字段,还可以指定一个方法
book_type = serializers.CharField(source='get_xx_display',read_only=True)
# #序列化出版社的详情,指定SerializerMethodField之后,可以对应一个方法,返回什么内容,publish_detail就是什么内容
publish_detail=serializers.SerializerMethodField(read_only=True)
#对应的方法固定写法get_字段名
def get_publish_detail(self,obj):
# print(type(obj))
return {'name':obj.publish.name,'city':obj.publish.city} #拓展性差
#返回所有作者信息
authors=serializers.SerializerMethodField(read_only=True)
def get_authors(self,obj):
# return [ {'name':author.name,'age':author.age} for author in obj.authors.all()]
authorser=AuthorSerializer(obj.authors.all(),many=True) #拓展性强
return authorser.data
def create(self, validated_data):
ret=models.Book.objects.create(**validated_data)
return ret
views部分
from app01.app01serializer import BookSerializer
class Books(APIView):
def get(self,request):
response={'code':100,'msg':'查询成功'}
books=models.Book.objects.all()
#如果序列化多条,many=True(也就是queryset对象,就需要写)
#如果序列化一条(可以不写),instance是要序列化的对象
bookser=BookSerializer(instance=books,many=True)
# print(type(bookser.data))
# bookser.data
response['data']=bookser.data
return Response(response)
反序列化
models部分不变
views部分
def post(self,request):
#实例化产生一个序列化类的对象,data是要反序列化的字典
# print(request.data)
bookser=BookSerializer(data=request.data)
if bookser.is_valid():
#清洗通过的数据,可以加限制比如最大长度之类的
ret=bookser.create(bookser.validated_data) #重写create方法,更新的话用update
return Response()
序列化之ModelSerializers
序列化
app01serializers部分
from rest_framework import serializers
from rest_framework import exceptions
from app01 import models
class BookSerializer(serializers.ModelSerializer):
class Meta:
model=models.Book
# fields=('nid','name')
#不能跟fields同时使用
# exclude=['name',]
fields=('__all__')
#深度是1,官方建议不要超过10,个人建议不要超过3
# depth=1
# xx=serializers.CharField(source='get_xx_display') #在外面重写字段(取中文)
# authors=serializers.SerializerMethodField()
# def get_authors(self,obj):
# ret=AuthorSerializer(instance=obj.authors.all(),many=True)
# return ret.data
# name=serializers.CharField()
#反序列化的校验(局部校验,全局校验)
def validate_name(self,value):
print(value)
raise exceptions.ValidationError('不能以sb开头')
# if value.startswith('sb'):
# raise ValidationError('不能以sb开头')
# return value
def validate(self,attrs):
print(attrs)
# if attrs.get('price')!=attrs.get('xx'):
# raise exceptions.ValidationError('name和price相等,不正常')
return attrs
views部分
def get(self,request):
response={'code':100,'msg':'查询成功'}
books=models.Book.objects.all()
#了解
# ret = serializers.serialize("json", books)
#如果序列化多条,many=True(也就是queryset对象,就需要写)
#如果序列化一条(可以不写),instance是要序列化的对象
bookser=BookSerializer(instance=books,many=True)
# print(type(bookser.data))
# bookser.data
response['data']=bookser.data
return Response(response)
反序列化
views部分
#使用继承了ModelSerializers序列化类的对象,反序列化
def post(self,request):
#实例化产生一个序列化类的对象,data是要反序列化的字典
bookser=BookSerializer(data=request.data)
# bookser.data
if bookser.is_valid(raise_exception=True):
#清洗通过的数据
bookser.save()
else:
print(bookser.errors['name'][0])
return Response()
反序列化的校验
validate_字段名(self,value)
如果校验失败,抛出validationError(抛出的异常信息需要去bookser.errors中取)
如果校验通过直接return value
validate(self,attrs)
attrs所有校验通过的数据,是个字典
如果校验失败,抛出validationError
如果校验通过直接return attrs
源码分析
序列化组件,先调用__new__方法,如果many=True,生成ListSerializer对象,如果为False,生成Serializer对象
序列化对象.data方法--调用父类data方法---调用对象自己的to_representation(自定义的序列化类无此方法,去父类找)
Aerializer类里有to_representation方法,for循环执行attribute = field.get_attribute(instance)
再去Field类里去找get_attribute方法,self.source_attrs就是被切分的source,然后执行get_attribute方法,source_attrs
当参数传过去,判断是方法就加括号执行,是属性就把值取出来