• RestFramework之序列化器源码解析


    一.源码解析之序列化:

    1.当视图类进行实例化序列化类做了如下操作:
    #ModelSerializer继承Serializer再继承BaseSerializer(此类定义实例化方法)
    #在BaseSerializer执行__new__方法,用于判断many是为True还是False:
    class BaseSerializer:
    	def __new__(cls, *args, **kwargs):
            if kwargs.pop('many', False):
                #many = True, 对QuerySet进行处理
                return cls.many_init(*args, **kwargs)
                #many = False  对对象进行处理, 然后执行初始化方法__init__
            return super().__new__(cls, *args, **kwargs)
    #当many=True:为QuerySet对象,用ListSerializer进行处理
    #当many=False:为单个对象,用Serializer进行处理
    
    
    
    • many=True,执行ListSerializerto_representation方法。 对于数据展示,一直调用ListSerializer
    
    class ListSerializer
        def to_representation(self, data):
    
            iterable = data.all() if isinstance(data, models.Manager) else data
    
            return [
            	#循环每一个数据库的对象,再根据每一个对象,去调用它的每个字段的to_representation来做显示
                self.child.to_representation(item) for item in iterable
            ]
    
    • many=False,执行自己Serializer
    #当执行自己Serializer
    class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
    	@property
        def data(self):
            #去父类执行data函数(父类BaseSerializer)
            ret = super().data
            #封装有序字典
            return ReturnDict(ret, serializer=self)
    #--------------------------------------------------------------------------
    class BaseSerializer:
        @property
        def data(self):
            if hasattr(self, 'initial_data') and not hasattr(self, '_validated_data'):
                msg = (
                    'When a serializer is passed a `data` keyword argument you '
                    'must call `.is_valid()` before attempting to access the '
                    'serialized `.data` representation.
    '
                    'You should either call `.is_valid()` first, '
                    'or access `.initial_data` instead.'
                )
                raise AssertionError(msg)
    
            if not hasattr(self, '_data'):
                if self.instance is not None and not getattr(self, '_errors', None):
                    self._data = self.to_representation(self.instance)
                elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
                    #执行to_representation,自己类中定义了此方法,去自己类中执行
                    self._data = self.to_representation(self.validated_data)
                else:
                    self._data = self.get_initial()
            return self._data
    #--------------------------------------------------------------------------
    class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
            def to_representation(self, instance):
            	ret = OrderedDict()
            	fields = self._readable_fields
    		#遍历循环每个field字段。field为我们序列化器写的每个字段。
            #序列化器中定义每个字段帮助我们去数据库里面把数据库字段拿取过来,通过Charfield,Interfield等类进行展示
                for field in fields:
                    try:
                    #去数据库中获取指定字段对应值
                    #比如:
                        #当filed为id,  此时attribute=1
                        #当filed为pwd, 此时attribute=123
                        #如果设置特殊字段如:HyperlinkedIdentityField,它只会把当前字段对象取出来:obj
                    attribute = field.get_attribute(instance)
                except SkipField:
                    continue
                check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
                if check_for_none is None:
                    ret[field.field_name] = None
                else:
                    #相当于:
                    """
                    {
                    	id:1, CharField
                    	pwd:123,  CharField
                    	group:obj,  HyperlinkedIdentityField
                    }
                    """
                    #通过每个字段类型再执行to_representation,
                    #因为有些字段一次无法拿到对应的值,所以,再通过各个字段的方法,如
                    #id:1 Charfield
                    #会执行field.to_representation(attribute) === Charfield.to_representation(1)
                    #Charfield中to_representation方法return six.text_type(value)  === return str(value)
                    
                    #而HyperlinkedIdentityField 执行to_representation,用反射方法去数据库找lookup_filed设置的字段,去数据库拿值,然后根据咱们之前设置好的look_url_kwargs的值(此值为url路由上设置动态参数名字)。然后通过这2个值通过reverse反向生成url.
                    ret[field.field_name] = field.to_representation(attribute)
    
            return ret
    
    • 未完待续,还差校验...
  • 相关阅读:
    文件
    购物车
    session
    三级联动
    综合
    jquery弹窗插件
    Jquery
    PDO
    session cookie用法
    租房子
  • 原文地址:https://www.cnblogs.com/xujunkai/p/11681087.html
Copyright © 2020-2023  润新知