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

浙公网安备 33010602011771号