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.21  Many=true
 
先调用ListSerializerdata属性

@property
def data(self):
    ret = super().data  # 调用父类data方法
   
return ReturnList(ret, serializer=self)

这里调用ListSerializer父类BaseSerializer的data方法
 
接着调用BaseSerializerdata属性

@property
def data(self):
    if not hasattr(self, '_data'):
        if self.instance is not None and not getattr(self, '_errors', None):
            #调用ListSerializerSerializer里面的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.22  Many=false
 
先调用用户自定义序列化类下父类Serializerdata属性

@property
def data(self):
    ret = super().data
    return ReturnDict(ret, serializer=self)

这里调用了父类的data属性,也就是BaseSerializer父类
 
接着调用BaseSerializerdata属性,上面已经写了,但是这里传入的self.instance只有一个模型实例
 
接着再调用Serializerto_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  # 返回构造的有序字典

 
 
posted @ 2021-05-07 18:57  落秋巴  阅读(103)  评论(0编辑  收藏  举报