1. 程式人生 > >django rest framework之序列化的原始碼流程剖析

django rest framework之序列化的原始碼流程剖析

當要對資料物件進行序化列例項化的時候

1     def __new__(cls, *args, **kwargs):
2         # We override this method in order to automagically create
3         # `ListSerializer` classes instead when `many=True` is set.
4         if kwargs.pop('many', False): #如果是QuerySet的時候
5             return cls.many_init(*args, **kwargs) #會呼叫ListSerializer
6 return super(BaseSerializer, cls).__new__(cls, *args, **kwargs)

 

當要對資料物件進行序列化的時候會呼叫到Serializer類中的to_representation方法

 1     def to_representation(self, instance):
 2         """
 3         Object instance -> Dict of primitive datatypes.
 4         """
 5         ret = OrderedDict() #生成有序字典
6 fields = self._readable_fields #獲取在我們在Serializer中定義的欄位(必須和models中的欄位名和型別一樣) 7 8 for field in fields: 9 try: 10 attribute = field.get_attribute(instance) #獲取欄位的物件 11 except SkipField: 12 continue 13 14 # We skip `to_representation` for `None` values so that fields do
15 # not have to explicitly deal with that case. 16 # 17 # For related fields with `use_pk_only_optimization` we need to 18 # resolve the pk value. 19 check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute 20 if check_for_none is None: 21 ret[field.field_name] = None 22 else: 23 ret[field.field_name] = field.to_representation(attribute) #封裝欄位的值(每個欄位型別可能不同) 24 25 return ret
 1     def get_attribute(self, instance):
 2         """
 3         Given the *outgoing* object instance, return the primitive value
 4         that should be used for this field.
 5         """
 6         try:
 7             return get_attribute(instance, self.source_attrs) #如果在欄位的source中定義瞭如:role.name(外來鍵)會被拆分成[role, name]
 8         except (KeyError, AttributeError) as exc:
 9             if self.default is not empty:
10                 return self.get_default()
11             if self.allow_null:
12                 return None
13             if not self.required:
14                 raise SkipField()
15             msg = (
16                 'Got {exc_type} when attempting to get a value for field '
17                 '`{field}` on serializer `{serializer}`.\nThe serializer '
18                 'field might be named incorrectly and not match '
19                 'any attribute or key on the `{instance}` instance.\n'
20                 'Original exception text was: {exc}.'.format(
21                     exc_type=type(exc).__name__,
22                     field=self.field_name,
23                     serializer=self.parent.__class__.__name__,
24                     instance=instance.__class__.__name__,
25                     exc=exc
26                 )
27             )
28             raise type(exc)(msg)
29 
30 def get_attribute(instance, attrs):
31     """
32     Similar to Python's built in `getattr(instance, attr)`,
33     but takes a list of nested attributes, instead of a single attribute.
34 
35     Also accepts either attribute lookup on objects or dictionary lookups.
36     """
37     for attr in attrs:
38         try:
39             if isinstance(instance, collections.Mapping):
40                 instance = instance[attr]
41             else:
42                 instance = getattr(instance, attr) #獲取物件的屬性(如果這個屬性還是一個數據實例物件的話就會再次迴圈呼叫)
43         except ObjectDoesNotExist:
44             return None
45         if is_simple_callable(instance): #判斷是不是一個函式
46             try:
47                 instance = instance()
48             except (AttributeError, KeyError) as exc:
49                 # If we raised an Attribute or KeyError here it'd get treated
50                 # as an omitted field in `Field.get_attribute()`. Instead we
51                 # raise a ValueError to ensure the exception is not masked.
52                 raise ValueError('Exception raised in callable attribute "{0}"; original exception was: {1}'.format(attr, exc))
53 
54     return instance