DRF的序列化与反序列化
序列化:
序列化:将模型,查询集转换成需要的格式的数据,比如json。一般为输出
model.py的内容如下:
1 | from django.db import models |
serializers.py的内容如下:
1 | from rest_framework import serializers |
使用序列化器序列化:
1 | from serializers import BookInfoSerializer |
关联序列化:
所谓关联序列化,就是当模型之间存在外键关联的时候,可以通过序列化这个表的时候,直接将关联的表也序列化掉。
1 | hero = HeroInfo.objects.get(id = 1) |
这里就会发现,
HeroInfoSerializer
中的hbook = serializer.PrimaryKeyRelatedField(lable = 'shuji', read_only = True)
序列化的是id。如果写为
hbook = serializer.StringRelatedField(lable = 'shuji', read_only = True)
是将__str__
函数的返回值序列化出来。如果写为
hbook = BookInfoSerializer()
会将关联的模型的所有字段序列化出来。
上面总共三种情况,都是在“一对多”中的“多”关联序列化的“一”,那如何在“一”中关联序列化“多”呢?
在BookInfoSerializer
中增加一个字段heroinfo_set = serializers.PrimaryKeyRelatedField(mang = True)
这个关联序列化的是id字段,当然也可以和上面一样,有__str__
函数等其他的序列化,比如heroinfo = HeroInfoSerialzier(many = True)
,当然,HeroInfoSerializer
要在这个类前面。
注意,在多中关联序列化一,或者一中关联序列化多,这两者,只能二选一。
总结:
反序列化:
反序列化:将前端数据转为模型数据。
首先先从前端拿到传来的数据,然后将其传给序列化器的data参数,然后调用序列化器的.is_valid()
方法进行校验,最后调用“序列化器.save()方法”。save方法,会根据传参情况,选择性的调用create方法或者update方法。create/update方法里面会再使用django的object.create方法保存至数据库。
1 | #反序列化: |
如果想要增加自己的数据校验方法,可以直接在序列化器中增加:
增加额外的校验
1.如果想要对一个字段增加校验,可以:(以在BookInfoSerializer
中增加校验为例)
1 | def validate_btitle(self, value): |
此方法的命名规则是validate_字段
, 此方法要return value
,如果不返回,后面还要的serializer.validated_data
就获取不到了。
2.如果想要对多个字段增加校验,可以:
1 | def validate(self,attrs): |
3.使用validators
比如我在BookInfoSerializer
中的一个字段中添加
1 |
|
所以,应用场景是,一个校验逻辑,多个字段都要以此去校验的时候,用这种写法。
serializer.save()
当我们校验成功之后,调用这个save方法会执行序列化器中的create或update方法。
根据save函数的源码可知,当这样调用序列化器的时候BookInfoSerializer(instance = book,data = dataa )
的时候,save
调用的是update
方法,如果只有data
传参,instance
没有接收到参数,那么save
函数就调用create
方法。
再看一下父类Serializer中的update和create方法没有实际的逻辑,所以,我们要save数据的时候,要在BookInfoSerializer中重构update方法和create方法。
1 | def create(self,validated_data): |
总结:
Serializer
的构造方法是serializer(instance= None, data = empty, **kwarg)
所以Book序列化器的构造函数为这个BookInfoSerialzier(instance , data, context)
第三个参数可以传字典。
ModelSerializer
ModelSerializer继承至Serializer
他比父类多的功能有:
1.他可以自动根据模型生成序列化器中的字段。
2.这个类帮我们实现了create和update方法。当然这些方法中的逻辑不一定是我们所需要的。
1 | class BookInfoSerializer(serializers.ModelSerializer): |
这样就直接按照BookInfo的模型的所有字段,生成了此序列化器中的字段。
序列化与反序列化如下:
1 | ser = BookInfoSerializer(book) |
BaseSerializer
DRF的serializer和ModelSerialzier 都继承至BaseSerializer
,所以,我们可以看看序列化器都有哪些基本的属性和方法。
该类实现与Serializer
类相同的基本API:
.data
- 返回传出的原始数据。(是python的原生数据,返回的数据应该是序列化的数据).is_valid()
- 反序列化并验证传入的数据。(是一个方法,返回True/False).validated_data
- 返回经过验证后的传入数据(是字典等python原生数据类型)。.errors
- 返回验证期间的错误。.save()
- 将验证的数据保留到对象实例中。(会调用create/update方法)
它还有可以覆写的四种方法,具体取决于你想要序列化类支持的功能:
.to_representation()
- 重写此方法来改变读取操作的序列化结果。.to_internal_value()
- 重写此方法来改变写入操作的序列化结果。.create()
和.update()
- 重写其中一个或两个来改变保存实例时的动作。
因为此类提供与Serializer
类相同的接口,所以你可以将它与现有的基于类的通用视图一起使用,就像使用常规Serializer
或ModelSerializer
一样。
这样做时你需要注意到的唯一区别是BaseSerializer
类并不会在可浏览的API页面中生成HTML表单。