1.Serializer实例化字段对象
最终内部会维护一个计数器,来表示实例化的先后顺序;后续会通过这个计数器排序,以此来实现字段的先后执行。
from app01 import models
from rest_framework import serializers
class DepartSerializer(serializers.Serializer):
id = serializers.IntegerField() # {max_value:111, _creation_counter:0}
title = serializers.CharField() # {allow_blank:Fakse, _creation_counter:1}
count = serializers.IntegerField() # {max_value:111, _creation_counter:2}
class IntegerField(Field):
def __init__(self, **kwargs):
self.max_value = kwargs.pop('max_value', None)
super().__init__(**kwargs)
def to_representation(self, value):
return int(value)
class CharField(Field):
def __init__(self, **kwargs):
self.allow_blank = kwargs.pop('allow_blank', False)
super().__init__(**kwargs)
def to_representation(self, value):
return str(value)
class Field:
_creation_counter = 0
def __init__(self, *, read_only=False, write_only=False,
required=None, default=empty, initial=empty, source=None,
label=None, help_text=None, style=None,
error_messages=None, validators=None, allow_null=False):
self._creation_counter = Field._creation_counter
Field._creation_counter += 1
2.序列化各种类继承关系
class SerializerMetaclass(type):
pass
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):
# We override this method in order to automatically create
# `ListSerializer` classes instead when `many=True` is set.
if kwargs.pop('many', False):
return cls.many_init(*args, **kwargs)
return super().__new__(cls, *args, **kwargs)
@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)
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 = 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):
self._data = self.to_representation(self.validated_data)
else:
self._data = self.get_initial()
return self._data
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
@property
def data(self):
ret = super().data
return ReturnDict(ret, serializer=self)
class ModelSerializer(Serializer):
pass
class TagModelSerializer(serializers.ModelSerializer):
pass
3.分析SerializerMetaclass【创建类】
class SerializerMetaclass(type):
@classmethod
def _get_declared_fields(cls, bases, attrs):
# fields = [(id, 对象), (title, 对象), (count, 对象)]
# if isinstance(obj, Field):如果对象是使用Field类建立的,返回结果为True
fields = [(field_name, attrs.pop(field_name)) for field_name, obj in list(attrs.items()) if isinstance(obj, Field)]
# 自己类中的对象进行排序
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) # {自己字段对象+父类字段对象}
return super().__new__(cls, name, bases, attrs)
4.数据库获取数据,序列化类
4.1 触发序列化 当前类 many=False
class Field:
def get_attribute(self, instance):
# source_attrs=[] 或 source_attrs=["xx","xx","xxx"]
return get_attribute(instance, self.source_attrs)
class CharField(Field):
def to_representation(self, value):
return str(value)
class BaseSerializer(Field):
@property
def data(self):
# 第2步
if not hasattr(self, '_data'):
if self.instance is not None and not getattr(self, '_errors', None):
# 第3步:用于序列化给对象进行初始化用的。
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:
# 这个是用于给Serializer,不传对象而传入initial_data参数用的。
self._data = self.get_initial()
return self._data
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
@property
def data(self):
# 第1步
ret = super().data
return ReturnDict(ret, serializer=self)
def to_representation(self, instance):
# 第4步
ret = OrderedDict()
# 第5步:获取 _declared_fields 中所有非write_only字段,即:用于序列化的字段。
# 如果是ModelSerializer,也会去寻找其Meta中定义的字段 + 字段的bind方法
fields = self._readable_fields
for field in fields:
try:
# 第5步:调用字段对象中的 get_attribute 方法
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:
# 第6步:调用字段对象中的 to_representation 方法
ret[field.field_name] = field.to_representation(attribute)
return ret
class ModelSerializer(Serializer):
...
class RoleSerializer(serializers.ModelSerializer):
gender = serializers.CharField(source="get_gender_display")
class Meta:
model = models.Role
fields = ["id", 'title',"gender"]
instance = models.UserInfo.objects.all().first()
ser = InfoSerializer(instance=instance, many=False)
# 创建InfoSerializer类的对象,获取序列化后的值
ser.data
4.2 触发序列化 ListSerializer many=True
class BaseSerializer(Field):
@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 ListSerializer(BaseSerializer):
@property
def data(self):
ret = super().data
return ReturnList(ret, serializer=self)
def to_representation(self, data):
iterable = data.all() if isinstance(data, models.Manager) else data
return [
# 循环,利用序列化类去处理每个对象
self.child.to_representation(item) for item in iterable
]