def field_to_native(self, obj, field_name): try: if self.source == '*': return self.to_native(obj) source = self.source or field_name value = obj for component in source.split('.'): if value is None: break value = get_component(value, component) except ObjectDoesNotExist: return None if value is None: return None if self.many: if is_simple_callable(getattr(value, 'all', None)): return [self.to_native(item) for item in value.all()] else: # Also support non-queryset iterables. # This allows us to also support plain lists of related items. return [self.to_native(item) for item in value] return self.to_native(value)
def get_attribute(self, instance): if self.use_pk_only_optimization() and self.source_attrs: # Optimized case, return a mock object only containing the pk attribute. try: instance = get_attribute(instance, self.source_attrs[:-1]) value = instance.serializable_value(self.source_attrs[-1]) if is_simple_callable(value): # Handle edge case where the relationship `source` argument # points to a `get_relationship()` method on the model value = value().pk return PKOnlyObject(pk=value) except AttributeError: pass # Standard case, return the object instance. return get_attribute(instance, self.source_attrs)
def field_to_native(self, obj, field_name): if self.many: # To-many relationship queryset = None if not self.source: # Prefer obj.serializable_value for performance reasons try: queryset = obj.serializable_value(field_name) except AttributeError: pass if queryset is None: # RelatedManager (reverse relationship) source = self.source or field_name queryset = obj for component in source.split('.'): if queryset is None: return [] queryset = get_component(queryset, component) # Forward relationship if is_simple_callable(getattr(queryset, 'all', None)): return [self.to_native(item.pk) for item in queryset.all()] else: # Also support non-queryset iterables. # This allows us to also support plain lists of related items. return [self.to_native(item.pk) for item in queryset] # To-one relationship try: # Prefer obj.serializable_value for performance reasons pk = obj.serializable_value(self.source or field_name) except AttributeError: # RelatedObject (reverse relationship) try: pk = getattr(obj, self.source or field_name).pk except (ObjectDoesNotExist, AttributeError): return None # Forward relationship return self.to_native(pk)
def get_attribute(self, instance): if self.use_pk_only_optimization() and self.source_attrs: # Optimized case, return a mock object only containing the pk attribute. try: attribute_instance = get_attribute(instance, self.source_attrs[:-1]) value = attribute_instance.serializable_value(self.source_attrs[-1]) if is_simple_callable(value): # Handle edge case where the relationship `source` argument # points to a `get_relationship()` method on the model. value = value() # Handle edge case where relationship `source` argument points # to an instance instead of a pk (e.g., a `@property`). value = getattr(value, 'pk', value) return PKOnlyObject(pk=value) except AttributeError: pass # Standard case, return the object instance. return super().get_attribute(instance)
def field_to_native(self, obj, field_name): """ Override default so that the serializer can be used as a nested field across relationships. """ if self.write_only: return None if self.source == '*': return self.to_native(obj) # Get the raw field value try: source = self.source or field_name value = obj for component in source.split('.'): if value is None: break value = get_component(value, component) except ObjectDoesNotExist: return None if is_simple_callable(getattr(value, 'all', None)): filtered_queryset = value.filter(self.get_related_filter()) return [self.to_native(item) for item in filtered_queryset] if value is None: return None if self.many is not None: many = self.many else: many = hasattr(value, '__iter__') and not isinstance(value, (Page, dict, six.text_type)) if many: return [self.to_native(item) for item in value] return self.to_native(value)
def to_representation(self, model: Model): value = getattr(model, self.custom_field_name) if is_simple_callable(value): return value() return value