1)先获取一个图书对象
from book.models import BookInfo
book = BookInfo.objects.get(id=1)
2)创建序列化器实例
from book.serializers import BookInfoSerializer
serializer = BookInfoSerializer(instance=book)
3)获取序列化的数据
serializer.data
结果:
{'is_delete': False, 'pub_date': '1987-11-11', 'readcount': 58, 'image': None, 'id': 4, 'commentcount': 24, 'name': '雪山飞狐'}
4)如果要被序列化的数据是包含多条数据的查询集QuerySet,可以通过添加many=True参数来补充说明。
book = BookInfo.objects.all()
serializer = BookInfoSerializer(instance=book,many=True) # 这里更改
serializer.data
[OrderedDict([('id', 3), ('name', '笑傲江湖'), ('pub_date', '1995-12-24'), ('readcount', 28), ('commentcount', 18), ('is_delete', False), ('image', None)]), OrderedDict([('id', 4),....])]
如果需要序列化的数据中包含其他关联对象,则对关联对象数据的序列化需要指明。
例如,在定义英雄数据的序列化器的时候,外键book(即所属图书)字段如何序列化?
咱们先来定义PeopleInfoSerializer除外键字段以外的其他部分
class PeopleInfoSerializer(serializers.Serializer):
"""英雄数据序列化器"""
GENDER_CHOICES = (
(0, 'male'),
(1, 'female')
)
id = serializers.IntegerField(label='ID', read_only=True)
name = serializers.CharField(label='名字', max_length=20)
gender = serializers.ChoiceField(choices=GENDER_CHOICES, label='性别', required=False)
description = serializers.CharField(label='描述信息', max_length=200, required=False, allow_null=True)
对于关联字段,咱们可以采用以下几种方式:
此字段将被序列化为关联对象的主键
book = serializers.PrimaryKeyRelatedField(label='图书',read_only=True)
或者
book = serializers.PrimaryKeyRelatedField(label='图书',queryset=BookInfo.objects.all())
指明字段的时候需要包含read_only=Trueu或者queryset参数
此字段将被序列化为关联对象的字符串表示方式(即____str____方法的返回值)
book = serialzers.StingRelatedField('label'=图书)
# 也可以再把id加上
book_id = serializers.IntegerField()
# 此时获取的就是ID和str返回的值 (这里设置的是name)
book = BookInfoSerialzer()
如果关联的对下那个数据不是只有一个,而是包含多个数据,如想序列化图书BookInfo数据,每个BookInfo对象关联的英雄PeopleInfo可能有多个,此时关联字段类型的指明仍可使用上面的机中方法,只是在声明关联字段的时候,多补充一个many=True参数即可
此处拿PrimaryKeyRelatedField类型来举例,其他相同。
在BookInfoSerializer中添加关联字段:
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
name = serializers.CharField(label='名称', max_length=20)
pub_date = serializers.DateField(label='发布日期', required=False)
readcount = serializers.IntegerField(label='阅读量', required=False)
commentcount = serializers.IntegerField(label='评论量', required=False)
image = serializers.ImageField(label='图片', required=False)
peopleinfo_set = serializers.PrimaryKeyRelatedField(many=True) # 这里更改
在使用序列化器进行反序列化的时候,需要对数据进行验证后,菜能获取验证成功的数据或者保存成模型类对象
在获取反序列化数据之前,必须调用**is_valid()**方法进行验证,验证成功返回True,否则返回False
在定义序列化器的时候,指明每个字段的序列化类型和选项参数,本身就是一种验证行为。
如咱们刚才在上面定义过的BookInfoSerializer
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
name = serializers.CharField(label='名称', max_length=20)
pub_date = serializers.DateField(label='发布日期', required=False)
readcount = serializers.IntegerField(label='阅读量', required=False)
commentcount = serializers.IntegerField(label='评论量', required=False)
image = serializers.ImageField(label='图片', required=False)
通过构造序列化器对象,并将要反序列化的数据传递给data构造参数,进而进行验证。
# 错误的
>>> from book.serializers import BookInfoSerializer
>>> data = {'pub_date':123}
>>> serializer = BookInfoSerializer(data=data)
>>> serializer.is_valid()
False
>>> serializer.errors
{'pub_date': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]].', code='invalid')], 'name': [ErrorDetail(string='This field is required.', code='required')]}
>>> serializer.validated_data
{}
# 正确的
正确
>>> from book.serializers import BookInfoSerializer
>>> data = {'pub_date':'2010-1-1','name':'python高级'}
>>> serializer = BookInfoSerializer(data=data)
>>> serializer.is_valid()
True
>>> serializer.errors
{}
>>> serializer.validated_data
OrderedDict([('name', 'python高级'), ('pub_date', datetime.date(2010, 1, 1))])
is_valid()方法还可以在验证失败的时候抛出异常serializers.ValidationError,可以通过传递raise_exception=True参数开启,REST framework接收到此异常,会向前端返回HTTP 400 Bad Request响应。
>>> from book.serializers import BookInfoSerializer
>>> data = {'pub_date':123}
>>> serializer = BookInfoSerializer(data=data)
>>> serializer.is_valid(raise_exception=True)
Traceback (most recent call last):
File "" , line 1, in <module>
File "/Users/yangjianmei/.virtualenvs/py3_django_1.11/lib/python3.5/site-packages/rest_framework/serializers.py", line 244, in is_valid
raise ValidationError(self.errors)
rest_framework.exceptions.ValidationError: {'pub_date': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]].', code='invalid')], 'name': [ErrorDetail(string='This field is required.', code='required')]}
>>> serializer.errors
{'pub_date': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]].', code='invalid')], 'name': [ErrorDetail(string='This field is required.', code='required')]}
>>> serializer.validated_data
{}
1)validate_
对
# 方法需要写在BookInfoSerializer序列化器的里面
class BookInfoSerializer(serializers.Serializer):
'''图书信息序列化器'''
id = ...
name = ...
def validate_readcount(self,value):
if value < 0 :
raise serializers.ValidationError("阅读量不能为负数")
return value
验证的话 还是根据以前的步骤进行验证, 记得把readcount数据改成负数再测试。
在序列化器中需要同时对多个字段进行验证的时候,可以使用validate方法:
# 方法需要写在BookInfoSerializer序列化器的里面
class BookInfoSerializer(serializers.Serializer):
'''图书信息序列化器'''
id = ...
name = ...
def validate(self,attrs):
readcount = attrs.get('readcount')
commentcount = attrs.get('commentount')
if commentcount > readcount:
raise serializers.ValidationError("评论量不能大于阅读量")
return attrs
在字段中添加validators选项参数,可以补充验证行为:
# 方法需要写在BookInfoSerializer序列化器的里面
class BookInfoSerializer(serializers.Serializer):
'''图书信息序列化器'''
def custom_validate(self):
raise serializers.ValidationError('出错!!')
id = ...
name = serializers.CharField(label='名称',max_length=20,validators=[custom_validate]) # 加参数
pub_date = ...
如果验证成功后,想要基于validated_data完成数据对象的创建,可以通过create()和update()方法来实现。
class BookInfoSerializer(serializers.Serializer):
"""图书数据序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
name = serializers.CharField(label='名称', max_length=20)
pub_date = serializers.DateField(label='发布日期', required=False)
readcount = serializers.IntegerField(label='阅读量', required=False)
commentcount = serializers.IntegerField(label='评论量', required=False)
image = serializers.ImageField(label='图片', required=False)
peopleinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增
def create(self, validated_data):
"""新建"""
return BookInfo.objects.create(**validated_data)
def update(self, instance, validated_data):
"""更新,instance为要更新的对象实例"""
instance.name = validated_data.get('name', instance.name)
instance.pub_date = validated_data.get('pub_date', instance.pub_date)
instance.readcount = validated_data.get('readcount', instance.readcount)
instance.commentcount = validated_data.get('commentcount', instance.commentcount)
instance.save()
# 或者:
instance = BookInfo.objects.filter(id=instance.id).update(**validated_data)
return instance
实现上面两个方法之后,在反序列化数据的时候,就可以通过save()方法返回一个数据对象实例了。
book = serializer.save()
如果创建序列化器对象的时候,没有传递instance实例,调用save()方法的时候,create()被调用,如果传递了instance实例,调用save()方法的时候,update()方法被调用
在对序列化器进行save()保存时候,可以额外传递数据,这些数据可以在create()和update()中的validated_data参数获取到
serializer.save(owner=request.user)
默认序列化器必须传递所有required的字段,否则会抛出验证异常,但是 们可以通过使用partial参数来允许部分字段更新
serializer = BookInfoSerializer(instance=book,data={'name','ok'},partila=True)
在执行save()方法之前必须先进行is_valid()方法验证。
如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serialzer类
ModelSerialzer与常规的Serializer相同,但提供了:
class BookInfoModelSerializer(serialzers.ModelSerializer):
class Meta:
model = BookInfo
fileds = '__all__'
我们可以在python manage.py shell 中查看自动生成的BookInfoSerializer的具体实现
>>> from book.serializers import BookInfoSerializer
>>> serializer = BookInfoSerializer()
>>> serializer
BookInfoSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(label='名称', max_length=20)
pub_date = DateField(label='发布日期', required=True)
readcount = IntegerField(label='阅读量', required=True)
commentcount = IntegerField(label='评论量', required=True)
image = ImageField(label='图片', required=False)
peopleinfo_set = PrimaryKeyRelatedField(many=True, read_only=True)
1) 使用fields来明确字段,__all__表名包含所有字段,也可以写明具体哪些字段,如
class BookInfoSerializer(serializers.ModelSerializer):
class Meta:
model = BookInfo
fields = '__all__'
2) 使用exclude可以明确排除掉哪些字段
class BookInfoSerializer(serializers.ModelSerializer):
class Meta:
model = BookInfo
exclude = ('image',)
3) 显示指明字段,如:
class BookInfoSerializer(serializers.ModelSerializer):
class Meta:
model = BookInfo
fields = ('id','name', 'readcount', 'commentcount')
4) 指明只读字段
可以通过read_only_fields指明只读字段,即仅用于序列化输出的字段
class BookInfoSerializer(serializers.ModelSerializer):
class Meta:
model = BookInfo
fields = ('id','name', 'readcount', 'commentcount')
read_only_fields = ('id', 'readcount', 'commentcount')
3. 添加额外参数
我们可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
class BookInfoSerializer(serializers.ModelSerializer):
class Meta:
model = BookInfo
fields = ('id','name', 'readcount', 'commentcount')
read_only_fields = ('id', 'readcount', 'commentcount')
extra_kwargs = {
'readcount': {'min_value': 0, 'required': True},
'commentcount': {'max_value': 0, 'required': True},
}
>>> from book.serializers import BookInfoSerializer
>>> serializer = BookInfoSerializer()
>>> serializer
BookInfoSerializer():
id = IntegerField(label='ID', read_only=True)
name = CharField(label='名称', max_length=20)
readcount = IntegerField(label='阅读量', min_value=0, read_only=True)
commentcount = IntegerField(label='评论量', max_value=0, read_only=True)