72. drf之序列化类的many参数_序列化类源码

1. 序列化类的many参数

 序列化时,many=True序列化器接收可迭代集合,序列化多条数据

      many=False序列化器接收单个对象,序列化单条数据

serializer.py

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        models = Book
        fields = '__all__'

在视图函数中:serializer = BookSerializer(待序列化的数据, many=True) 

当调用序列化类BookSerializer时,会触发其_ _init_ _函数

序列化类中没有这个函数,去基类ModelSerializer中查找

再去Serializer--BaseSerializer中有_ _init_ _函数.

    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)

many=True传给了kwargs

kwargs.pop('many', None)的含义:

1. 从字典kwargs取出键many对应的值;
2. 取出后,会把 many这个键直接从 kwargs 里删掉;
3. 如果 kwargs 里面不存在 many,就返回默认值 None。

 

如何控制对象的生成:类( )    先运行_ _new_ _是创建对象   再运行_ _init_ _完成对象初始化

通过重写_ _new_ _控制对象的生成

加了many=True,会运行_ _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,调用many_init完成对象的创建
return cls.many_init(*args, **kwargs)
     # manu=False,调用序列化类完成对象的创建
return super().__new__(cls, *args, **kwargs)

 

    @classmethod
    def many_init(cls, *args, **kwargs):
        list_kwargs = {}
        for key in LIST_SERIALIZER_KWARGS_REMOVE:
            value = kwargs.pop(key, None)
            if value is not None:
                list_kwargs[key] = value
        list_kwargs['child'] = cls(*args, **kwargs)
        list_kwargs.update({
            key: value for key, value in kwargs.items()
            if key in LIST_SERIALIZER_KWARGS
        })
        meta = getattr(cls, 'Meta', None)  # 在类cls中反射Meta,cls就是序列化类
        # 如果有meta,则为list_serializer_class,没有则为ListSerializer
     list_serializer_class
= getattr(meta, 'list_serializer_class', ListSerializer) return list_serializer_class(*args, **list_kwargs)

对应着自定义的序列化类就是去反射该类的Meta

而之前没有在序列化类中重写过'list_serializer_class',因此list_serializer_class的值默认为ListSerializer

所以都是通过return ListSerializer(*args, **list_kwargs)实例化得到对象

ListSerializer的本质:[BookSerializer对象1, BookSerializer对象2, BookSerializer对象3]

结论:

  传入many=True,序列化类的Meta中默认不重写'list_serializer_class'的情况下,是由ListSerializer生成的对象

  传入many=False,是由自定义的序列化类生成的对象

举例:

serializer1 = BookSerializer(instance=Book.objects.all(), many=True)
serializer2 = BookSerializer(instance=Book.objects.all())

这两个serializer看起来都是BookSerialize生成的对象,实际上serializer1是ListSerializer生成的对象,serializer2才是BookSerialize生成的对象

 

在Meta中定义list_serializer_class参数,用于控制序列化多条数据时用哪个序列化类

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        models = Book
        fields = '__all__'
        list_serializer_class = ...

2. 序列化类源码

 app01的views.py

from rest_framework.views import APIView
from rest_framework.response import Response
from .serializer import BookSerializer

class BookView(APIView):
    def get(self, request):
        serializer = BookSerializer()
        serializer.is_valid()
        return Response('查询所有')

只要运行is_valid,就会运行字段本身的校验、局部钩子、全局钩子

is_valid的源码

    def is_valid(self, *, raise_exception=False):
        assert hasattr(self, 'initial_data'), (
            'Cannot call `.is_valid()` as no `data=` keyword argument was '
            'passed when instantiating the serializer instance.'
        )

        if not hasattr(self, '_validated_data'):
            try:
                self._validated_data = self.run_validation(self.initial_data)
            except ValidationError as exc:
                self._validated_data = {}
                self._errors = exc.detail
            else:
                self._errors = {}

        if self._errors and raise_exception:
            raise ValidationError(self.errors)

        return not bool(self._errors)

如果之前没有调用过is_valid,就会运行self._validated_data = self.run_validation(self.initial_data)

如果之前调用过is_valid有_validated_data,就不会再运行if not hasattr(self, '_validated_data')

run_validation得到校验过后的数据

自定义序列化组件--查看is_valid源码--按住control查看run_validation源码(这时查看的源码是错误的,查看的是self基类的run_validation源码)

要从自定义序列化组件--基类ModelSerializer--基类Serializer查看run_validation源码

    def run_validation(self, data=empty):
        (is_empty_value, data) = self.validate_empty_values(data)
        if is_empty_value:
            return data
        # 局部钩子
        value = self.to_internal_value(data)
        try:
            self.run_validators(value)
# 全局钩子 value = self.validate(value) assert value is not None, '.validate() should return the validated data' except (ValidationError, DjangoValidationError) as exc: raise ValidationError(detail=as_serializer_error(exc)) return value

查看to_internal_value(局部钩子)的源码

    def to_internal_value(self, data):
        for field in fields:

       # self是序列化类的对象
            # 去序列化类的对象中反射validate_字段名
            validate_method = getattr(self, 'validate_' + field.field_name, None)
            primitive_value = field.get_value(data)
            try:
                validated_value = field.run_validation(primitive_value)

          # 能反射到,就会运行,即写了局部钩子就会运行这句,不写就不会运行
                if validate_method is not None:
                    validated_value = validate_method(validated_value)
            except ValidationError as exc:
                errors[field.field_name] = exc.detail
            except DjangoValidationError as exc:
                errors[field.field_name] = get_error_detail(exc)
            except SkipField:
                pass
            else:
                self.set_value(ret, field.source_attrs, validated_value)

        if errors:
            raise ValidationError(errors)

        return ret

 

  

posted @ 2026-10-05 02:08  pythondjango  阅读(4)  评论(0)    收藏  举报