一.源碼解析之序列化:
1.當視圖類進行實例化序列化類作了以下操做:
#ModelSerializer繼承Serializer再繼承BaseSerializer(此類定義實例化方法)
#在BaseSerializer執行__new__方法,用於判斷many是爲True仍是False:
class BaseSerializer:
def __new__(cls, *args, **kwargs):
if kwargs.pop('many', False):
#many = True, 對QuerySet進行處理
return cls.many_init(*args, **kwargs)
#many = False 對對象進行處理, 而後執行初始化方法__init__
return super().__new__(cls, *args, **kwargs)
#當many=True:爲QuerySet對象,用ListSerializer進行處理
#當many=False:爲單個對象,用Serializer進行處理
- 當
many=True
,執行ListSerializer
中to_representation
方法。 對於數據展現,一直調用ListSerializer
class ListSerializer
def to_representation(self, data):
iterable = data.all() if isinstance(data, models.Manager) else data
return [
#循環每個數據庫的對象,再根據每個對象,去調用它的每一個字段的to_representation來作顯示
self.child.to_representation(item) for item in iterable
]
- 當
many=False
,執行本身Serializer
#當執行本身Serializer
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
@property
def data(self):
#去父類執行data函數(父類BaseSerializer)
ret = super().data
#封裝有序字典
return ReturnDict(ret, serializer=self)
#--------------------------------------------------------------------------
class BaseSerializer:
@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,本身類中定義了此方法,去本身類中執行
self._data = self.to_representation(self.validated_data)
else:
self._data = self.get_initial()
return self._data
#--------------------------------------------------------------------------
class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
def to_representation(self, instance):
ret = OrderedDict()
fields = self._readable_fields
#遍歷循環每一個field字段。field爲咱們序列化器寫的每一個字段。
#序列化器中定義每一個字段幫助咱們去數據庫裏面把數據庫字段拿取過來,經過Charfield,Interfield等類進行展現
for field in fields:
try:
#去數據庫中獲取指定字段對應值
#好比:
#當filed爲id, 此時attribute=1
#當filed爲pwd, 此時attribute=123
#若是設置特殊字段如:HyperlinkedIdentityField,它只會把當前字段對象取出來:obj
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:
#至關於:
"""
{
id:1, CharField
pwd:123, CharField
group:obj, HyperlinkedIdentityField
}
"""
#經過每一個字段類型再執行to_representation,
#由於有些字段一次沒法拿到對應的值,因此,再經過各個字段的方法,如
#id:1 Charfield
#會執行field.to_representation(attribute) === Charfield.to_representation(1)
#Charfield中to_representation方法return six.text_type(value) === return str(value)
#而HyperlinkedIdentityField 執行to_representation,用反射方法去數據庫找lookup_filed設置的字段,去數據庫拿值,而後根據我們以前設置好的look_url_kwargs的值(此值爲url路由上設置動態參數名字)。而後經過這2個值經過reverse反向生成url.
ret[field.field_name] = field.to_representation(attribute)
return ret