09-序列化器的 many=True 实现原理

发布时间 2023-12-06 16:39:02作者: yaowy

入门知识

上面说明了,解释器会先执行 new 方法,再执行 init方法
下面说明了,如果new返回的空对象不是当前init对应的类型,就不会执行init。

序列化器 many=True 的简化版

可以看到 many_init 方法返回的是 Alist的空对象,而不是 A 的空对象,因此,没有 A init 打印

1. BookSerializer(data=data, many=True)

BaseSerializer 是个基类,上面语句执行之后,图片中这四处地方按照序号执行。
【1】首先执行的是 __new__方法,如果参数中可以弹出一个 many,则走 many_init 类方法
【2】先将所有的参数放到当前的序列化起类中,然后变成参数,生成了一个 list_kwargs 字典,并将其传递给了默认的 ListSerializer 列表序列化器[如果没有在 Meta 里面配置的话],这里返回的是一个对象,于是又要走一遍【1】
由于第二次走【1】,已经去掉了many参数,所有走的是常规的new方法,也就是代码块【3】
执行完了【3】之后,返回的是一个列表序列化器的空对象,紧接着解释器会调用【4】完成初始化
【4】这次执行的是 列表序列化器的初始化
最终【1】返回的是列表序列化器完成了初始化的对象。由于这个对象不是非列表序列化器的对象,因此不会再执行初始化操作了。

列表序列化器的data

这里尝试返回一个 ReturnList 对象,但是这个对象只是python列表的加强版,因此最终还是要看 ret = super().data这行代码,也就是最终还是调用 BaseSerializer.data 方法。

BaseSerializer.data

这里有三种返回,其中两个返回的是 to_representation 方法的返回值,一个返回的是 get_initial 的返回值,那我们先去看看 get_initial 的代码,注意 ListSerializer 也有该方法,所以最终调用的是 ListSerializer 的 get_initial 方法

最终还是调用 to_representation 方法。所以我们需要去看看 ListSerializer.to_representation

ListSerializer.to_representation

【1】如果data是一个 Manager 对象,则调用 data.all() 否则就使用 data本身
【2】遍历每一个元素,并且调用 Serializer.to_representation 方法,完成序列化

总结 Serializer 和 ListSerializer 均继承自 BaseSerializer,在两个类的 to_representation 方法了实现了调用的统一。