Django rest Framework(DRF)源码解析——序列化
四.序列化
4.1 第一步实例化序列器类
执行类的实例化,一般就是封装一些数据变量,所以不需要看源码看得太多。
我们来看实例化过程中的两个魔法方法,init方法和new方法
自定义的序列化器类没有init方法,先走得是爷爷类BaseSerializer里面的init方法,然后这里面的init方法再调用BaseSerializer的父类Field类的init方法。
在init方法之前会先执行new方法。New方法返回一个类的实例对象空间,传递给init方法的self,然后init方法进行属性赋值。New方法是有基类object所提示的,所以一般new方法里面的返回值都是return super.__new__(cls)。
BaseSerializer的__new__方法
def __new__(cls, *args, **kwargs):
# We override this method in order to
automatically create
# `ListSerializer` classes instead
when `many=True` is set.
if kwargs.pop('many', False):
# 当many=true时,返回ListSerializer,然后执行ListSerializer里面的init方法
return cls.many_init(*args, **kwargs)
# 当many=false时,返回自定义的序列化类,然后执行自定义的序列化类里面的init方法
return cls.many_init(*args, **kwargs)
return super().__new__(cls, *args, **kwargs)
4.2 第二步调用序列化器的data方法
4.2.1 Many=true时
先调用ListSerializer的data属性
@property
def data(self):
ret = super().data # 调用父类data方法
return ReturnList(ret, serializer=self)
这里调用ListSerializer父类BaseSerializer的data方法
接着调用BaseSerializer的data属性
@property
def data(self):
if not hasattr(self, '_data'):
if self.instance is not None and not getattr(self, '_errors', None):
#调用ListSerializer或Serializer里面的to_representation
self._data = self.to_representation(self.instance)
elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
self._data = self.to_representation(self.validated_data)
else:
self._data = self.get_initial()
return self._data
这里调用ListSerializer里的to_representation函数。self.instance是我们传入的多个模型实例
接着调用ListSerializer 的to_representation函数
def to_representation(self, data):
"""
List of object instances -> List of dicts of primitive datatypes.
"""
# 模型实例列表转换为原生数据类型列表
# Dealing with nested relationships, data can be a Manager,
# so, first get a queryset from the Manager if needed
iterable = data.all() if isinstance(data, models.Manager) else data
return [self.child.to_representation(item) for item in iterable ]
# iterable里面为一个个的模型实例对象,对每一个对象调用to_representation方法
这里会继续调用Serializer里面的to_representation
4.2.2 Many=false时
先调用用户自定义序列化类下父类Serializer的data属性
@property
def data(self):
ret = super().data
return ReturnDict(ret, serializer=self)
这里调用了父类的data属性,也就是BaseSerializer父类
接着调用BaseSerializer的data属性,上面已经写了,但是这里传入的self.instance只有一个模型实例
接着再调用Serializer的to_representation函数
def to_representation(self, instance):
"""
序列化 Object instance -> Dict of primitive datatypes.
"""
ret = OrderedDict()
fields = self._readable_fields # 保证现在的fields都是read_only的,即可以进行序列化的字段
for field in fields:
try:
attribute = field.get_attribute(instance)
'''调用字段的get_attribute方法,获取字段的值字段没有调用父类Field类的 get_attribute传入模型实例对象,获取对象字段对应的值'''
except SkipField:
continue
# We skip `to_representation` for `None` values so that fields do
# not have to explicitly deal with that case.
#
# For related fields with `use_pk_only_optimization` we need to
# resolve the pk value.
check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
if check_for_none is None:
ret[field.field_name] = None
else:
# 进行对字段的to_representation,如CharField里的to_representation,把attribute转成字符串, IntegerField的字段转换成整型。
ret[field.field_name] = field.to_representation(attribute)
# 如构造成了字典{'id': 1, 'username': '徐豪华', 'pwd': '123', 'password': '123', 'roles': [1, 2]}
return ret # 返回构造的有序字典