序列化源码流程
在创建类的时候,是先将成员变量和方法创建,将成员变量和方法作为参数传递给基类type()
class base(serializers.Serializer):
id = serializers.IntegerField(source='id')
name = serializers.CharField(source='name')
字段xx是先于base类创建的
1、创建成员变量
#第4部分会用到
def get_attribute(instance, attrs):
#atrrs是source按.分个开的列表
#depart = serializers.CharField(source='depart.title')
#attrs=['depart','title']
for attr in attrs:
try:
if isinstance(instance, Mapping):
instance = instance[attr]
else:
#先获取depart对象赋值给instance,循环到第二次的时候从depart获取title
instance = getattr(instance, attr)
except ObjectDoesNotExist:
return None
if is_simple_callable(instance): #是否可执行
try:
#gender_text = serializers.CharField(source='get_gender_display')
instance = instance()
except (AttributeError, KeyError) as exc:
# If we raised an Attribute or KeyError here it'd get treated
# as an omitted field in `Field.get_attribute()`. Instead we
# raise a ValueError to ensure the exception is not masked.
raise ValueError('Exception raised in callable attribute "{}"; original exception was: {}'.format(attr, exc))
return instance
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):
self.max_value = kwargs.pop('max_value', None)
self.min_value = kwargs.pop('min_value', None)
#调用父类的__init__
super().__init__(**kwargs)
if self.max_value is not None:
message = lazy_format(self.error_messages['max_value'], max_value=self.max_value)
self.validators.append(
MaxValueValidator(self.max_value, message=message))
if self.min_value is not None:
message = lazy_format(self.error_messages['min_value'], min_value=self.min_value)
self.validators.append(
MinValueValidator(self.min_value, message=message))
def to_representation(self, value):
return int(value)
def bind(self, field_name, parent):
#读取字段的source
#name = serializers.CharField(source='name')
#depart = serializers.CharField(source='depart.title') -->source_attrs=['depart','title']
if self.source == '*':
self.source_attrs = []
else:
self.source_attrs = self.source.split('.')
# 4 部分会用到
def get_attribute(self, instance):
#source_attrs就是source的值,4部分的get_attritube就会获取instance.name等等
#return 的get_attribute不是Field的方法
return get_attribute(instance, self.source_attrs)
class CharField(Field):
def __init__(self, **kwargs):
self.allow_blank = kwargs.pop('allow_blank', False)
self.trim_whitespace = kwargs.pop('trim_whitespace', True)
self.max_length = kwargs.pop('max_length', None)
self.min_length = kwargs.pop('min_length', None)
#也调用父类的__init__
super().__init__(**kwargs)
...
def to_representation(self, value):
return str(value)
id = serializers.IntegerField(source='id') #{'max_value':xxx, '_creation_counter':0}
#等到name字段创建时,Field的_creation_counter+=1
name = serializers.CharField(source='name') #{'allow_blank':xxx, '_creation_counter':1}
Field维护一个_creation_counter变量的意义是什么?
是根据编写的顺序来定义后续源码中各个字段的处理顺序。因为字典是无序的,当有校验的需求时应该要有固定的字段执行顺序
2、创建类
class base(serializers.Serializer): #继承Serializer
xx = serializers.IntegerField(source='count')
name = serializers.CharField(source='name')
class D1(serializers.ModelSerializer):
class Meta:
model = models.Depart
fields = ['id','title']
#也是继承Serializer
class ModelSerializer(Serializer):
...
#由SerializerMetaclass创建
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
...
class SerializerMetaclass(type):
@classmethod
def _get_declared_fields(cls, bases, attrs):
#循环类的所有成员,isinstance(obj, Field)可以获取所有继承Field类的对象
#isinstance(name,Field) True
#isinstance(name,CharField) True
#列表推导式获取Field对象之后pop将对象取出到元组里(field_name,Field对象)
#fields = [('id',IntegerField对象),('xx',CharField对象)]
fields = [(field_name, attrs.pop(field_name))
for field_name, obj in list(attrs.items())
if isinstance(obj, Field)]
#根据对象的_creation_counter排序,这里的fields是自己的字段
fields.sort(key=lambda x: x[1]._creation_counter)
#元组去重
known = set(attrs)
def visit(name):
known.add(name)
return name
#bases:父类,寻找父类的_declared_fields(在__new__时创建的),并转换成列表套元组
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)
return super().__new__(cls, name, bases, attrs)
3、收到请求,查询数据库 + 序列化器
class UserView(APIView):
def get(self,request,*args,**kwargs):
#查询数据库获取并序列化
queryset = models.UserInfo.objects.all()
#many的值不同创建的类也是不同的
ser = UserSerializer(instance=queryset,many=True) #最终会使用BaseSerializer来创建类
#ser = UserSerializer(instance=queryset,many=False)
class UserSerializer(serializers.ModelSerializer,base):
...
class ModelSerializer(Serializer):
...
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
...
class BaseSerializer(Field):
def __new__(cls, *args, **kwargs):
#pop参数里的many,如果没有many择返回默认值False
if kwargs.pop('many', False):
return cls.many_init(*args, **kwargs) #many=True,使用many_init,返回ListSerializer对象
return super().__new__(cls, *args, **kwargs)#mant=False,返回当前对象UserSerializer
def __init__(self, instance=None, data=empty, **kwargs):
self.instance = instance
@classmethod
def many_init(cls, *args, **kwargs):
allow_empty = kwargs.pop('allow_empty', None)
max_length = kwargs.pop('max_length', None)
min_length = kwargs.pop('min_length', None)
#实例化当前类:UserSerializer()
child_serializer = cls(*args, **kwargs)
list_kwargs = {
'child': child_serializer,
}
if allow_empty is not None:
list_kwargs['allow_empty'] = allow_empty
if max_length is not None:
list_kwargs['max_length'] = max_length
if min_length is not None:
list_kwargs['min_length'] = min_length
list_kwargs.update({
key: value for key, value in kwargs.items()
if key in LIST_SERIALIZER_KWARGS
})
#读取Meta成员
meta = getattr(cls, 'Meta', None)
#读取Meta里的list_serializer_class
list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
#返回一个实例化对象list_serializer_class(),将实例化的当前对象child_serializer()当做参数传递
return list_serializer_class(*args, **list_kwargs)
4、触发序列化ser.data(many=False的情况)
class UserView(APIView):
def get(self,request,*args,**kwargs):
queryset = models.UserInfo.objects.all()
ser = UserSerializer(instance=queryset,many=False)
class UserSerializer(serializers.ModelSerializer,base):
...
class ModelSerializer(Serializer):
def get_fields(self):
...
#深拷贝_declared_fields
declared_fields = copy.deepcopy(self._declared_fields)
#寻找model字段,model = models.UserInfo
model = getattr(self.Meta, 'model')
depth = getattr(self.Meta, 'depth', 0)
...
#将数据库的字段都获取
info = model_meta.get_field_info(model)
field_names = self.get_field_names(declared_fields, info)#读取fields,获取数据库对应的字段
# Determine any extra field arguments and hidden fields that
# should be included
extra_kwargs = self.get_extra_kwargs()
extra_kwargs, hidden_fields = self.get_uniqueness_extra_kwargs(
field_names, declared_fields, extra_kwargs
)
# Determine the fields that should be included on the serializer.
fields = OrderedDict()
#将定义的字段对应的对象进行循环
for field_name in field_names: #如果字段在models的类名里,直接添加到fields
# If the field is explicitly declared on the class then use that.
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
#如果字段名不在数据库,则根据对应关系创建,build_field会调用build_standard_field,里面会根据serializer_field_mapping的对应关系创建
#models.CharField对应Serializer的CharField
field_class, field_kwargs = self.build_field(
source, info, model, depth
)
# Include any kwargs defined in `Meta.extra_kwargs`
field_kwargs = self.include_extra_kwargs(
field_kwargs, extra_field_kwargs
)
# Create the serializer field.
fields[field_name] = field_class(**field_kwargs)
# Add in any hidden fields.
fields.update(hidden_fields)
#返回创建的字段对应的对象
return fields
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
@cached_property
def fields(self):
fields = BindingDict(self)
#循环self.get_fields,会先在子类ModelSerializer找,get_fields返回的包括自己定义的字段和Meta的Fields的字段
for key, value in self.get_fields().items():
fields[key] = value
return fields
@property
def _readable_fields(self):
#循环self.fields,并返回
for field in self.fields.values():
if not field.write_only:
yield field
#序列化功能,由data触发
def to_representation(self, instance):
ret = OrderedDict() #有序字典
fields = self._readable_fields #获取所有的字段,在第2部分的UserSerializer._get_declared_fields + 读取Meta里的fields字段并创建对象
#循环所有的对象
for field in fields:
...
#执行每个字段的get_attribute--(IntegerField.get_attribute)->在第一部分
#获取数据库对应的字段
attribute = field.get_attribute(instance)
#调用每个field的to_representation,整形转换成整形,char->str...
'''
class IntegerField(Field):
def to_representation(self, value):
return int(value)
'''
ret[field.field_name] = field.to_representation(attribute)
return ret
@property
def data(self):
ret = super().data #调用父类的data
return ReturnDict(ret, serializer=self)
class BaseSerializer(Field):
@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.\n'
'You should either call `.is_valid()` first, '
'or access `.initial_data` instead.'
)
raise AssertionError(msg)
if not hasattr(self, '_data'):
#instance在调用序列化器时就已经传递
if self.instance is not None and not getattr(self, '_errors', None):
#序列化的功能to_representation,在子类Serializer
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
流程:
实例化UserSerializer类,UserSerializer的data由@property装饰,调用父类的data。在BaseSerializer类才有data方法,执行data时会用到子类Serializer的to_representation,这个方法会调用_readable_fields通过get_fields获取declared_fields的字段和Meta的字段并实例化成对象,返回给to_representation,to_representation根据字段名(通过get_attritube获取到数据库对应的值)获取值,再返回给有序字典data。
、
5、触发序列化ser.data(many=True的情况)
class UserView(APIView):
def get(self,request,*args,**kwargs):
queryset = models.UserInfo.objects.all()
ser = UserSerializer(instance=queryset,many=True)
context = {'status': 200, 'data': ser.data}
return Response(context)
class BaseSerializer(Field):
def __new__(cls, *args, **kwargs):
if kwargs.pop('many', False):
return cls.many_init(*args, **kwargs) #many = True,->many_init()
return super().__new__(cls, *args, **kwargs)
@classmethod
def many_init(cls, *args, **kwargs):
child_serializer = cls(*args, **kwargs)
list_kwargs = {
'child': child_serializer,} #将当前类UserSerializer当做参数传递给list_serializer_class->list_kwargs:{'child': child_serializer}
meta = getattr(cls, 'Meta', None)
list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
return list_serializer_class(*args, **list_kwargs)
@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.\n'
'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,会找到子类ListSerializer的此方法
self._data = self.to_representation(self.validated_data)
else:
self._data = self.get_initial()
return self._data
#many=True的情况调用ser.data
class ListSerializer(BaseSerializer):
...
child = None
many = True
@property
def __init__(self, *args, **kwargs):
self.child = kwargs.pop('child', copy.deepcopy(self.child))
def data(self):
ret = super().data #调用父类的data
return ReturnList(ret, serializer=self)
def to_representation(self, data):
iterable = data.all() if isinstance(data, models.Manager) else data
#列表生成式,循环调用当前类的to_representation
return [
self.child.to_representation(item) for item in iterable
]
many=True的情况就是第4部分加上一个循环。
图片来源:武佩齐老师