django rest framework之序列化的原始碼流程剖析
阿新 • • 發佈:2018-11-21
當要對資料物件進行序化列例項化的時候
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) #會呼叫ListSerializer6 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 do15 # 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