drf源码剖析----序列化--(字段、类、对象)

点击查看代码
class Field:
    _creation_counter = 0

    def __init__(self):
        self._creation_counter = Field._creation_counter
        Field._creation_counter += 1

class IntegerField(Field):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def to_representation(self, value):
        return int(value)

class CharField(Field):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def to_representation(self, value):
        return str(value)

id = serializers.IntegerField()       # _creation_counter = 0
title = serializers.CharField()       # _creation_counter = 1
order = serializers.IntegerField()    # _creation_counter = 2

# 根据编写顺序定义后续开发过程中各个字段的处理顺序

点击查看代码
class Field:
    def get_attribute(self, instance):
       return get_attribute(instance, self.source_attrs)

class SerializerMetaclass(type):
    @classmethod
    def _get_declared_fields(cls, bases, attrs):
     # fields = [(), (), ()]
        fields = [(field_name, attrs.pop(field_name))
                  for field_name, obj in list(attrs.items())
                  if isinstance(obj, Field)]
        # 基于_creation_counter排序, 自己类中的字段对象
        fields.sort(key=lambda x: x[1]._creation_counter) 
        known = set(attrs)  # 去重

        def visit(name):
            known.add(name)
            return name
        # 父类中的字段对象
        base_fields = [
            (visit(name), f)
            for base in bases if hasattr(base, '_declared_fields')
            for name, f in base._declared_fields.items() if name not in known
        ]

        return OrderedDict(base_fields + fields)

    def __new__(cls, name, bases, attrs):
        attrs['_declared_fields'] = cls._get_declared_fields(bases, attrs)
        # 创建类TestSerializer()
        return super().__new__(cls, name, bases, attrs)  

class BaseSerializer(Field):
     def __init__(self, instance=None, data=empty, **kwargs):
        self.instance = instance
        if data is not empty:
            self.initial_data = data
        self.partial = kwargs.pop('partial', False)
        self._context = kwargs.pop('context', {})
        kwargs.pop('many', None)
        super().__init__(**kwargs)

    def __new__(cls, *args, **kwargs):
        if kwargs.pop('many', False):
            return cls.many_init(*args, **kwargs)
        return super().__new__(cls, *args, **kwargs)

    @classmethod
    def many_init(cls, *args, **kwargs):
        child_serializer = cls(*args, **kwargs)  # obj = TestSerializer()
        list_kwargs = {
            'child': child_serializer,
        }
        meta = getattr(cls, 'Meta', None)
        list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
      # 实例化ListSerializer(child_serializer)
        return list_serializer_class(*args, **list_kwargs)

    @property
    def data(self):
        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):
                self._data = self.to_representation(self.validated_data)
            else:
                self._data = self.get_initial()
        return self._data

class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
    # 基于SerializerMetaclass创建类
    @property
    def data(self):
        ret = super().data 
        # 调用父类BaseSerializer()的data
        return ReturnDict(ret, serializer=self)

    def to_representation(self, instance):
        ret = OrderedDict()
# 获取所有字段,TestSerializer._declared_fields+Meta里fields字段创建的对象 
        fields = self._readable_fields    
        for field in fields:
            attribute = field.get_attribute(instance)
            ret[field.field_name] = field.to_representation(attribute)
        return ret
    
    @property
    def _readable_fields(self):
        for field in self.fields.values():
            if not field.write_only:
                yield field

    @cached_property
    def fields(self):
        fields = BindingDict(self)
        for key, value in self.get_fields().items():
            fields[key] = value
        return fields


class ModelSerializer(Serializer):
    def get_fields(self):
        if self.url_field_name is None:
            self.url_field_name = api_settings.URL_FIELD_NAME

        assert hasattr(self, 'Meta'), (
            'Class {serializer_class} missing "Meta" attribute'.format(
                serializer_class=self.__class__.__name__
            )
        )
        assert hasattr(self.Meta, 'model'), (
            'Class {serializer_class} missing "Meta.model" attribute'.format(
                serializer_class=self.__class__.__name__
            )
        )
        if model_meta.is_abstract_model(self.Meta.model):
            raise ValueError(
                'Cannot use ModelSerializer with Abstract Models.'
            )

        declared_fields = copy.deepcopy(self._declared_fields)
        model = getattr(self.Meta, 'model')
        depth = getattr(self.Meta, 'depth', 0)

        if depth is not None:
            assert depth >= 0, "'depth' may not be negative."
            assert depth <= 10, "'depth' may not be greater than 10."

        info = model_meta.get_field_info(model)
        field_names = self.get_field_names(declared_fields, info)

        extra_kwargs = self.get_extra_kwargs()
        extra_kwargs, hidden_fields = self.get_uniqueness_extra_kwargs(
            field_names, declared_fields, extra_kwargs
        )

        fields = OrderedDict()

        for field_name in field_names:
            if field_name in declared_fields:
                fields[field_name] = declared_fields[field_name]
                continue

            extra_field_kwargs = extra_kwargs.get(field_name, {})
            source = extra_field_kwargs.get('source', '*')
            if source == '*':
                source = field_name

            field_class, field_kwargs = self.build_field(
                source, info, model, depth
            )

            field_kwargs = self.include_extra_kwargs(
                field_kwargs, extra_field_kwargs
            )

            fields[field_name] = field_class(**field_kwargs)

        fields.update(hidden_fields)

        return fields


点击查看代码
# 创建类
class TestSerializer(serializers.ModelSerializer):
    id = 123
    age = serializers.IntegerField(source='age')
    gender = serializers.CharField(source='get_gender_display')
    depart = serializers.CharField(source='depart.title')
    datetime = serializers.DateTimeField(format='%Y-%m-%d')

    class Meta:
        model = models.Member
        fields = ['name', 'age', 'gender', 'depart', 'datetime']

TestSerializer._declared_fields  # 获取序列化类中的所有字段 

# 用户请求到来,数据库获取数据,序列化当前类
queryset = models.Member.objects.all()
 # ListSerializer(TestSerializer)
ser = TestSerializer(instance=queryset,many=True)

instance = models.Member.objects.all().first()
ser = TestSerializer(instance=instance, many=False)  # TestSerializer

# ser.data 触发序列化
posted @   周亚彪  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示