Django-rest-framework源码分析(二)

四、Serializer对象的data属性

  在《Django-rest-framework源码分析(一)》中我分析了Serializer对象实例化的过程,而Serializer类的其他方法并没有涉及。

  序列化最重要的是拿到对象序列化后的结果,这个结果被保存在了序列化对象的.data属性中。下面重点来看.data属性

  入口 serializer_obj.data

  rest_framework/serializers.py/class Serializer/def data()

  

  它是一个被包装成属性的方法,在方法中执行了父类的data方法,并且把父类.data的返回值转化成ReturnDict数据类型返回。

  rest_framework/serializers.py/class BaseSerializer/def data()

  

  红框内的部分实现了一种类似单例的模式,当序列化对象有_data属性的时候,直接返回,不调用函数,这就避免了资源的浪费,去重复执行一些函数(因为每一次执行的结果都是相同的)。它的实现方式是利用反射查找属性_data是否存在,如果不存在,把要返回的结果设置给_data属性,下次再调用data()函数的时候,就直接返回了self._data。

  进入if语句中,只要self没有错误属性,且instance不为空或者有_validated_data属性,都会执行一个.to_representation的方法,只是传的参数不同。

  rest_framework/serializers.py/class BaseSerializer/def __init__()

  

  当我们序列化一个数据对象的时候,一般是直接位置传参,数据对象被参数instance接收,这个时候instance不为空,我们再看BaseSerializer的data方法。

  rest_framework/serializers.py/class BaseSerializer/def data()

   

  rest_framework/serializers.py/class Serializer/def to_representation()

  

  真正进行序列化操作的是Serializer类重写的to_representation方法,它将每一个字段都进行了字段自己的校验,然后放入OrderDict有序字典中,再将有序字典返回。这个有序字典在Serializer的def data方法中用ReturnDict加工之后,就是最后的serializer_obj.data返回对象了。

五、Serializer校验相关

  我们先大概看一些反序列化的过程。

  rest_framework/serializers.py/class BaseSerializer/def __init__()

  

  可以看到,序列化组件对象把传入的data直接赋值给了self的initial_data属性。

  序列化入口 rest_framework/serializes.py/class BaseSerializer/def is_valid()

  

  这里也是用了一种类似单例的模式,避免了重复校验,校验后的结果存放在self的_validated_data属性当中,生成校验后结果的函数是run_validation(),捕获异常,并把异常放在self._error当中,如果_error不为空且raise_exception的Boolean为True时,会直接抛异常。最后返回一个Boolean值。

  rest_framework/serializes.py/class Serializer/def run_validation()

  

  先调用to_internal_value返回一个value,再以value为参数分别执行run_validators和validate方法。最后返回的是valiate方法的返回值。

   如果在我们自己写的序列化类中重写了全局钩子,也就是def validate(),那么最后一步就会执行我们自己写的全局钩子进行校验。如果没有就走模块自己的validate方法,这个方法没有进行任何操作,直接把传入的参数作为返回值返回了。

  to_internal_value方法是局部钩子的校验。

  rest_framework/serializes.py/class Serializer/def to_internal_value()

   

  这是to_internal_value方法的部分源码,它先找了我们自己写的局部钩子校验的方法,然后将数据传入,校验后返回。传入的是单个的数据。

以上是Serializer相关的源码

posted @ 2019-07-05 21:33  Aokigahara  阅读(585)  评论(1编辑  收藏  举报