def _update_flattened_field(self, validated_data, instance=None, related_objects=None): assert not (instance and related_objects ), "cannot pass both instance and related_objects" for field_name, (serializer_class, source) in self._flattened_fields.items(): if field_name in validated_data: partial = self.partial try: obj = get_attribute(instance, source.split('.')) except (AttributeError, KeyError): obj = get_attribute(related_objects, source.split('.')) partial = True except (AttributeError, KeyError): obj = None serializer = serializer_class( instance=obj, data=validated_data.pop(field_name), context=self.context, partial=partial) serializer.is_valid(raise_exception=True) serializer.save()
def get_attribute(self, instance): # We customize `get_attribute` here for performance reasons. # For relationships the instance will already have the pk of # the related object. We return this directly instead of returning the # object itself, which would require a database lookup. try: instance = get_attribute(instance, self.source_attrs[:-1]) return PKOnlyObject(pk=instance.serializable_value(self.source_attrs[-1])) except AttributeError: return get_attribute(instance, self.source_attrs)
def extract_lookup(self, instance, key, lookup) -> Any: lookup_path = lookup.split('.') if lookup_path[0] == 'self': return get_attribute( self.parent.instance, lookup_path[1:] ) else: return get_attribute( instance, lookup_path )
def get_attribute(self, instance): # We customize `get_attribute` here for performance reasons. # For relationships the instance will already have the pk of # the related object. We return this directly instead of returning the # object itself, which would require a database lookup. try: instance = get_attribute(instance, self.source_attrs[:-1]) return PKOnlyObject( pk=instance.serializable_value(self.source_attrs[-1])) except AttributeError: return get_attribute(instance, self.source_attrs)
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]) return PKOnlyObject(pk=instance.serializable_value(self.source_attrs[-1])) except AttributeError: pass # Standard case, return the object instance. return get_attribute(instance, self.source_attrs)
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]) return PKOnlyObject( pk=instance.serializable_value(self.source_attrs[-1])) except AttributeError: pass # Standard case, return the object instance. return get_attribute(instance, self.source_attrs)
def process_source(self, object_list, source): new_object_list = [] for obj in object_list: value = obj value = get_attribute(value, source.split('.')) new_object_list.append(value) return new_object_list
def get_attribute(self, instance): # Can't have any relationships if not created if hasattr(instance, 'pk') and instance.pk is None: return [] relationship = get_attribute(instance, self.source_attrs) return relationship.all() if (hasattr(relationship, 'all')) else relationship
def get_attribute(self, instance): # Can't have any relationships if not created if hasattr(instance, "pk") and instance.pk is None: return [] relationship = get_attribute(instance, self.source_attrs) return relationship.all() if hasattr(relationship, "all") else relationship
def get_attribute(self, instance): # Can't have any relationships if not created if not instance.pk: return [] relationship = get_attribute(instance, self.source_attrs) return relationship.all() if (hasattr(relationship, "all")) else relationship
def _get_related_model_field(self, nested_serializer): """Return model field through that nested serializer relate with parent and type of relation. :param nested_serializer: :return: Tuple contained model field and relation type (`forward`, `reverse`). """ assert len(nested_serializer.source_attrs) == 1, "We don't support fields with complex source." related_descriptor = get_attribute( self.Meta.model, nested_serializer.source_attrs ) if isinstance(related_descriptor, related_descriptors.ReverseOneToOneDescriptor): return related_descriptor.related.field, 'forward' if isinstance(related_descriptor, related_descriptors.ReverseManyToOneDescriptor): return related_descriptor.field, 'forward' if (isinstance( related_descriptor, related_descriptors.ForwardManyToOneDescriptor ) and isinstance(related_descriptor.field, related.OneToOneField)): return related_descriptor.field, 'reverse' assert False, "We don't support many to many relation and forward many to one " \ "because updating this relation have side effect."
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 get_attribute_smart(instance, attrs): """A bit smarter version of rest_framework.fields.get_attribute. Has ability to work with lists, so it can be used to look deep inside relations. Also is suitable for dicts. Example usage: get_attribute_smart({"instances": [{"id": 1}, {"id": 2}, {"id": 3}]}, "instances.id") """ if instance is None or not attrs: return instance if isinstance(attrs, six.string_types): attrs = attrs.split('.') if isinstance( instance, (Iterable, QuerySet)) and not isinstance(instance, (Mapping, six.string_types)): instance = list( [get_attribute_smart(obj, [attrs[0]]) for obj in instance]) if all(map(lambda obj: isinstance(obj, QuerySet), instance)): instance = chain(*instance) else: instance = get_attribute(instance, [attrs[0]]) if isinstance(instance, Manager): instance = instance.all() return get_attribute_smart(instance, attrs[1:])
def to_representation(self, instance): agg_op = self.get_agg_op(instance) real_instance = self.get_real_instance(instance) child = self.resolve_child_type(real_instance, agg_op) transformed_instance = {'aggregates': real_instance} for field, (field_serializer, initial) in self.get_aggregate_types_and_defaults( real_instance, agg_op).items(): transformed_instance[self.get_aggregate_field_name( field, real_instance, agg_op)] = initial self.fields[self.get_aggregate_field_name( field, real_instance, agg_op)] = field_serializer for obj in real_instance: for field in self.get_aggregate_types_and_defaults( real_instance, agg_op): value = get_attribute(obj, [field]) transformed_instance[self.get_aggregate_field_name( field, real_instance, agg_op)] = self.top_level_reduce( transformed_instance[self.get_aggregate_field_name( field, real_instance, agg_op)], value, ) self.fields['aggregates'] = serializers.ListField(child=child, ) return super(AggregateListSerializer, self).to_representation(transformed_instance)
def _get_attribute(self, instance): # Can't have any relationships if not created if hasattr(instance, 'pk') and instance.pk is None: return [] try: relationship = get_attribute(instance, self.source_attrs) except (KeyError, AttributeError) as exc: if self.default is not empty: return self.get_default() if self.allow_null: return None if not self.required: raise SkipField() msg = ('Got {exc_type} when attempting to get a value for field ' '`{field}` on serializer `{serializer}`.\nThe serializer ' 'field might be named incorrectly and not match ' 'any attribute or key on the `{instance}` instance.\n' 'Original exception text was: {exc}.'.format( exc_type=type(exc).__name__, field=self.field_name, serializer=self.parent.__class__.__name__, instance=instance.__class__.__name__, exc=exc, )) raise type(exc)(msg) return relationship.all() if hasattr(relationship, 'all') else relationship
def get(self, request): user = request.user forms_context_dict = {} form_class_context_key_user_field_tuples = [ [InstituteAddressForm, 'insti_address_form', ('insti_address',)], [ProgramForm, 'program_form', ('program',)], [SexUpdateForm, 'sex_update_form', ('userprofile', 'sex',)], ] for form_class, context_key, user_attr in form_class_context_key_user_field_tuples: try: form = form_class(initial=attr_to_dict(get_attribute(user, user_attr), key=user_attr[-1])) except (AttributeError, ObjectDoesNotExist): form = form_class() forms_context_dict[context_key] = form mobile_numbers = ContactNumber.objects.all().filter(user=user).order_by('-id') secondary_emails = SecondaryEmail.objects.all().filter(user=user).order_by('-id') user_profile = user.userprofile gpo_email = user.email ldap_number = user_profile.mobile roll_number = user_profile.roll_number request_context = { 'mobile_numbers': mobile_numbers, 'secondary_emails': secondary_emails, 'gpo_email': gpo_email, 'ldap_number': ldap_number, 'roll_number': roll_number, 'user_profile_picture': model_field_media_url(user.userprofile.profile_picture), } request_context.update(forms_context_dict) return render(request, 'user_resources/home.html', request_context)
def get_attribute(self, instance): # Can't have any relationships if not created if not instance.pk: return [] relationship = get_attribute(instance, self.source_attrs) return relationship.all() if (hasattr(relationship, 'all')) else relationship
def get_url(self, obj, view_name, request, format): if hasattr(obj, 'pk') and obj.pk is None: return None lookup_url_kwargs = {} for lookup_field, lookup_url_kwarg in zip(self.lookup_fields, self.lookup_url_kwargs): lookup_value = get_attribute(obj, lookup_field.replace('__', '.').split('.')) lookup_url_kwargs[lookup_url_kwarg] = lookup_value return self.reverse(view_name, kwargs=lookup_url_kwargs, request=request, format=format)
def should_redact(self, instance, context=None): if self.user_field and self.parent: request = (context or self.context).get("request", None) if request and hasattr(request, "user"): user = get_attribute(instance, self.user_field.split(".")) return not request.user.id is user.id return True else: return False
def get_attribute_override(self, instance): # Override the default implementation of get_attribute # Can't have any relationships if not created if hasattr(instance, 'pk') and instance.pk is None: return [] relationship = get_attribute(instance, self.source_attrs) queryset = filter_relationship(self, instance, relationship) return queryset.all() if (hasattr(queryset, 'all')) else queryset
def get_url(self, obj, view_name, request, format): url = super().get_url(obj, view_name, request, format) if url and self.__query_params: get = lambda x: x(obj) if callable(x) else get_attribute(obj, x.split('.')) params = [(key, get(value)) for key, value in self.__query_params.items()] url = url + '?' + urlencode(params) return url
def get_attribute(self, instance): """ Given the *outgoing* object instance, return the primitive value that should be used for this field. """ try: return fields.get_attribute(instance, self.source_attrs) except (KeyError, AttributeError) as exc: return None if self.default == fields.empty else self.default
def __call__(self, new_value): # no instance -> it's not an update if not self.instance: return current_value = get_attribute(self.instance, self.serializer_field.source_attrs) if new_value != current_value: raise serializers.ValidationError(self.message, code=self.code)
def get_owner_of(self, obj): try: meta = getattr(self, 'Meta', None) owner_attr = getattr(meta, 'owner_attr') except KeyError: return None if owner_attr == '*': return obj return get_attribute(obj, owner_attr.split('.'))
def update(self, instance, validated_data): if isinstance(instance, models.Manager): instance = instance.all() exists_instances = {i.pk: i for i in instance} excess_instances_pks = set(exists_instances.keys()) model = self.child.Meta.model result = list() errors = list() has_error = False for data in validated_data: errors.append(dict()) # PK used to detect exists objects. try: pk = get_attribute(data, self.child.pk_field.source_attrs) except KeyError: pk = None try: if pk: if pk not in exists_instances: raise serializers.ValidationError({ self.child.pk_field.field_name: _('{} with pk `{}` doesn\'t exists.').format( model._meta.verbose_name.title(), pk), }) if pk not in excess_instances_pks: raise serializers.ValidationError({ self.child.pk_field.field_name: _('Duplication {} with pk `{}`.').format( model._meta.verbose_name, pk) }) excess_instances_pks.remove(pk) result.append(self.child.update(exists_instances[pk], data)) else: result.append(self.child.create(data)) except serializers.ValidationError as exc: has_error = True errors[-1] = serializers.as_serializer_error(exc) if has_error: raise serializers.ValidationError(errors) if excess_instances_pks and not getattr(self.root, 'partial', False): model._default_manager.filter(pk__in=excess_instances_pks).delete() return result
def get_related_instance(self): parent_obj = self.get_object() parent_serializer = self.serializer_class(parent_obj) field_name = self.get_related_field_name() field = parent_serializer.fields.get(field_name, None) if field is not None: try: instance = field.get_attribute(parent_obj) except SkipField: instance = get_attribute(parent_obj, field.source_attrs) else: if isinstance(instance, PKOnlyObject): # need whole object instance = get_attribute(parent_obj, field.source_attrs) return instance else: try: return getattr(parent_obj, field_name) except AttributeError: raise NotFound
def get_attribute(self, instance): # Can't have any relationships if not created. if hasattr(instance, 'pk') and instance.pk is None: return [] queryset = self.queryset if hasattr(queryset, '__call__'): queryset = queryset(self.child_relation, instance) else: relationship = get_attribute(instance, self.source_attrs) queryset = relationship.all() if (hasattr(relationship, 'all')) else relationship return queryset
def get_attribute(self, obj, requested_language=None): source = self.source or self.field_name field = fields.get_attribute(obj, source.split(".")) if not field: return None request = self.context.get("request", None) if requested_language is None: if request and request.method == "GET" and "lang" in request.GET: requested_language = request.GET["lang"] if requested_language: return self.fetch_single_translation(obj, source, field, requested_language) else: return self.fetch_all_translations(obj, source, field)
def extract_relation_instance(cls, field, resource_instance): """ Determines what instance represents given relation and extracts it. Relation instance is determined exactly same way as it determined in parent serializer """ try: res = field.get_attribute(resource_instance) if isinstance(res, PKOnlyObject): return get_attribute(resource_instance, field.source_attrs) return res except SkipField: return None
def get_url(self, obj, view_name, request, format): # pylint: disable=redefined-builtin # Unsaved objects will not yet have a valid URL. if hasattr(obj, 'pk') and obj.pk in (None, ''): return None if self.lookup_fields: kwargs = { key: get_attribute(obj, value.split('__')) for key, value in zip(self.lookup_url_kwargs, self.lookup_fields) } return self.reverse(view_name, kwargs=kwargs, request=request, format=format) return super().get_url(obj, view_name, request, format)
def get_attribute(self, obj, requested_language=None): source = self.source or self.field_name field = fields.get_attribute(obj, source.split('.')) if not field: return None request = self.context.get('request', None) if requested_language is None: if request and request.method == 'GET' and 'lang' in request.GET: requested_language = request.GET['lang'] if requested_language: return self.fetch_single_translation(obj, source, field, requested_language) else: return self.fetch_all_translations(obj, source, field)
def get(self, request): user = request.user forms_context_dict = {} form_class_context_key_user_field_tuples = [ [InstituteAddressForm, 'insti_address_form', ('insti_address', )], [ProgramForm, 'program_form', ('program', )], [SexUpdateForm, 'sex_update_form', ( 'userprofile', 'sex', )], ] for form_class, context_key, user_attr in form_class_context_key_user_field_tuples: try: form = form_class(initial=attr_to_dict( get_attribute(user, user_attr), key=user_attr[-1])) except (AttributeError, ObjectDoesNotExist): form = form_class() forms_context_dict[context_key] = form mobile_numbers = ContactNumber.objects.all().filter( user=user).order_by('-id') secondary_emails = SecondaryEmail.objects.all().filter( user=user).order_by('-id') user_profile = user.userprofile gpo_email = user.email ldap_number = user_profile.mobile roll_number = user_profile.roll_number request_context = { 'mobile_numbers': mobile_numbers, 'secondary_emails': secondary_emails, 'gpo_email': gpo_email, 'ldap_number': ldap_number, 'roll_number': roll_number, 'user_profile_picture': model_field_media_url(user.userprofile.profile_picture), } request_context.update(forms_context_dict) return render(request, 'user_resources/home.html', request_context)
def get_url(self, obj, view_name, request, format): # Unsaved objects will not have a valid URL. if hasattr(obj, 'pk') and obj.pk in (None, ''): return None # get lookup map (will use properties lookup_map and view) lookup_map = self._lookup_map get = lambda x: x(obj) if callable(x) else get_attribute( obj, x.split('.')) # build kwargs for reverse try: kwargs = dict( ((key, get(source)) for (key, source) in lookup_map.items())) except (KeyError, AttributeError) as exc: raise ValueError( "Got {exc_type} when attempting to create url for field " "`{field}` on serializer `{serializer}`. " "The serializer field lookup_map might be configured incorrectly. " "We used `{instance}` instance with lookup map `{lookup_map}`. " "Original exception text was: {exc}.".format( exc_type=type(exc).__name__, field=self.field_name, serializer=self.parent.__class__.__name__, instance=obj.__class__.__name__, lookup_map=lookup_map, exc=exc, )) try: return self.reverse(self.view_name, kwargs=kwargs, request=request, format=format) except NoReverseMatch as exc: raise ImproperlyConfigured( "Could not resolve URL for hyperlinked relationship in field " "`{field}` on serializer `{serializer}`. " "You may have failed to include the related model in your API, " "or incorrectly configured `view_name` or `lookup_map` " "attribute on this field. Original error: {exc}".format( field=self.field_name, view_name=self.view_name, serializer=self.parent.__class__.__name__, kwargs=kwargs, exc=exc, ))
def _relation_to_json(field, value=None, many=None): serializer = field.serializer if many is None: many = field.many name_field_name = serializer.get_name_field() name_source = serializer.get_field( name_field_name ).source or name_field_name source_attrs = name_source.split('.') value = value or field.value if not ( isinstance(value, list) and not isinstance(value, six.string_types) and not isinstance(value, UUID) ): value = [value] results = [] model = serializer.get_model() for v in value: if v: if hasattr(v, 'instance'): instance = v.instance else: if v is None: continue else: if isinstance(v, model): instance = v else: instance = model.objects.get( pk=str(v) ) result = { 'id': str(instance.pk), 'name': get_attribute(instance, source_attrs) } results.append(result) if not many: # single value result results = results[0] if len(results) else None return mark_safe(json.dumps(results))
def get_url(self, obj, view_name, request, format): """ Given an object, return the URL that hyperlinks to the object. May raise a `NoReverseMatch` if the `view_name` is not configured to correctly match the URL conf. """ # Unsaved objects will not yet have a valid URL. if hasattr(obj, 'pk') and obj.pk in (None, ''): return None kwargs = {} for field, kwarg in self.multi_lookup_map.items(): kwargs[kwarg] = get_attribute(obj, field.split('.')) return self.reverse(view_name, kwargs=kwargs, request=request, format=format)
def get_attribute(self, obj): source = self.source or self.field_name try: field = fields.get_attribute(obj, source.split('.')) except AttributeError: field = None if not field: return None requested_language = self.get_requested_language() if requested_language: single = self.fetch_single_translation(obj, source, field, requested_language) return list(single.values())[0] if single and self.flat else single else: return self.fetch_all_translations(obj, source, field)
def get_attribute(self, obj): source = self.source or self.field_name field = fields.get_attribute(obj, source.split('.')) if not field: return None requested_language = None request = self.context.get('request', None) if request and request.method == 'GET' and 'lang' in request.GET: requested_language = request.GET['lang'] if requested_language: return self.fetch_single_translation(obj, source, field, requested_language) else: return self.fetch_all_translations(obj, source, field)
def get_attribute(self, instance): if hasattr(instance, 'pk') and instance.pk is None: return [] attr = self.source_attrs[-1] # `gc` 是 `GroupConcat` 的缩写 gc_attr = f'gc_{attr}' if hasattr(instance, gc_attr): gc_value = getattr(instance, gc_attr) if isinstance(gc_value, str): return [UUID(pk) for pk in set(gc_value.split(','))] else: return '' relationship = get_attribute(instance, self.source_attrs) return relationship.all() if hasattr(relationship, 'all') else relationship
def get_serializer_class(self, instance=None, data=empty): """ Returns the appropriate serializer to use for given data or instance. """ if instance is not None: for cls, (name, serializer) in self._declared_classes.items(): if cls == instance.__class__: return serializer elif data is not empty: try: type_value = get_attribute(data, [self.type_field]) except KeyError: raise ValidationError('No type specified.') for name, (cls, serializer) in self._declared_types.items(): if name == type_value: return serializer return
def zip_instance_extra_with_iterable(instance, iterable, extra): extra_attrs = dict( (key, get_attribute(instance, attrs.split('.'))) for key, attrs in extra.items() ) return (AttributeProxy(item, **extra_attrs) for item in iterable)
def get_iterable(self, instance, source): relationship = get_attribute(instance, [source]) return relationship.all() if (hasattr(relationship, 'all')) else relationship
def get_url(self, obj, view_name, request, format): url_kwargs = { self.parent_lookup_url_kwarg: get_attribute(obj, self.parent_lookup_field.replace('__', '.').split('.')), self.lookup_url_kwarg: get_attribute(obj, self.lookup_field.replace('__', '.').split('.')), } return self.reverse(view_name, kwargs=url_kwargs, request=request, format=format)
def get_attribute(self, instance): if instance.is_tax_known: return super(TaxIncludedDecimalField, self).get_attribute(instance) if self.excl_tax_field: return get_attribute(instance, (self.excl_tax_field, )) return self.excl_tax_value
def get_attribute(self, instance): return get_attribute(instance, self.source_attrs)
def get_attribute(self, instance): relationship = get_attribute(instance, self.source_attrs) return relationship.all() if (hasattr(relationship, 'all')) else relationship
def extract_included(fields, resource, resource_instance, included_resources): # this function may be called with an empty record (example: Browsable Interface) if not resource_instance: return included_data = list() current_serializer = fields.serializer context = current_serializer.context include_config = utils.get_included_configuration(current_serializer) included_resources = copy.copy(included_resources) for field_name, field in six.iteritems(fields): # Skip URL field if field_name == api_settings.URL_FIELD_NAME: continue # Skip fields without relations or serialized data if not isinstance(field, (relations.RelatedField, relations.ManyRelatedField, BaseSerializer)): continue # Skip disabled fields if include_config[field_name] == False: continue try: included_resources.remove(field_name) except ValueError: # Skip fields not in requested included resources continue try: relation_instance_or_manager = get_attribute(resource_instance, field.source.split('.')) except AttributeError: try: # For ManyRelatedFields if `related_name` is not set we need to access `foo_set` from `source` relation_instance_or_manager = get_attribute(resource_instance, field.child_relation.source.split('.')) except AttributeError: if not hasattr(current_serializer, field.source): continue serializer_method = get_attribute(current_serializer, field.source.split('.')) relation_instance_or_manager = serializer_method(resource_instance) new_included_resources = [key.replace('%s.' % field_name, '', 1) for key in included_resources if field_name == key.split('.')[0]] serializer_data = resource.get(field_name) serializer_instances = [] if isinstance(field, relations.ManyRelatedField): # # serializer_class = include_config.get(field_name) # serializer_class = utils.get_serializer_from_instance_and_serializer() # serializer_instance = serializer_class(relation_instance_or_manager.all(), many=True, context=context) if isinstance(current_serializer.instance, Iterable): iterable = [] for obj in current_serializer.instance: iterable += field.get_attribute(obj) else: iterable = field.get_attribute(current_serializer.instance) for item in iterable: serializer_class = utils.get_serializer_from_instance_and_serializer(item, current_serializer, field_name) serializer_instance = serializer_class(item, context=context) serializer_instances.append(serializer_instance) if isinstance(field, relations.RelatedField): # serializer_class = include_config.get(field_name) if relation_instance_or_manager is None: continue serializer_class = utils.get_serializer_from_instance_and_serializer(relation_instance_or_manager, current_serializer, field_name) serializer_instance = serializer_class(relation_instance_or_manager, context=context) serializer_instances.append(serializer_instance) for serializer_instance in serializer_instances: serializer_data = serializer_instance.data relation_type = utils.get_resource_type_from_serializer(serializer_instance.__class__) # Get the serializer fields serializer_fields = utils.get_serializer_fields(serializer_instance) if serializer_data: included_data.append( JSONRenderer.build_json_resource_obj( serializer_fields, serializer_data, serializer_instance.instance, relation_type) ) included_data.extend( JSONRenderer.extract_included( serializer_fields, serializer_data, serializer_instance.instance, new_included_resources ) ) return utils.format_keys(included_data)
def extract_relationships(fields, resource, resource_instance): # Avoid circular deps from rest_framework_json_api.relations import ResourceRelatedField data = OrderedDict() # Don't try to extract relationships from a non-existent resource if resource_instance is None: return for field_name, field in six.iteritems(fields): # Skip URL field if field_name == api_settings.URL_FIELD_NAME: continue # Skip fields without relations if not isinstance(field, (relations.RelatedField, relations.ManyRelatedField, BaseSerializer)): continue source = field.source try: relation_instance_or_manager = get_attribute(resource_instance, source.split('.')) except AttributeError: # if the field is not defined on the model then we check the serializer # and if no value is there we skip over the field completely serializer_method = getattr(field.parent, source, None) if serializer_method and hasattr(serializer_method, '__call__'): relation_instance_or_manager = serializer_method(resource_instance) else: continue # relation_type = utils.get_related_resource_type(field) if isinstance(field, relations.HyperlinkedIdentityField): relation_type = utils.get_related_resource_type(field) # special case for HyperlinkedIdentityField relation_data = list() # Don't try to query an empty relation relation_queryset = relation_instance_or_manager.all() \ if relation_instance_or_manager is not None else list() for related_object in relation_queryset: relation_data.append( OrderedDict([('type', relation_type), ('id', encoding.force_text(related_object.pk))]) ) data.update({field_name: { 'links': { "related": resource.get(field_name)}, 'data': relation_data, 'meta': { 'count': len(relation_data) } }}) continue if isinstance(field, ResourceRelatedField): # special case for ResourceRelatedField relation_data = { 'data': resource.get(field_name) } field_links = field.get_links(resource_instance) relation_data.update( {'links': field_links} if field_links else dict() ) data.update({field_name: relation_data}) continue if isinstance(field, (relations.PrimaryKeyRelatedField, relations.HyperlinkedRelatedField)): relation_id = relation_instance_or_manager.pk if resource.get(field_name) else None relation_type = utils.get_related_resource_type(field) relation_data = { 'data': ( OrderedDict([('type', relation_type), ('id', encoding.force_text(relation_id))]) if relation_id is not None else None) } relation_data.update( {'links': {'related': resource.get(field_name)}} if isinstance(field, relations.HyperlinkedRelatedField) and resource.get(field_name) else dict() ) data.update({field_name: relation_data}) continue if isinstance(field, relations.ManyRelatedField): if isinstance(field.child_relation, ResourceRelatedField): # special case for ResourceRelatedField if field_name not in resource: continue relation_data = { 'data': resource.get(field_name) } field_links = field.child_relation.get_links(resource_instance) relation_data.update( {'links': field_links} if field_links else dict() ) relation_data.update( { 'meta': { 'count': len(resource.get(field_name)) } } ) data.update({field_name: relation_data}) continue relation_data = list() for related_object in relation_instance_or_manager.all(): related_object_type = utils.get_instance_or_manager_resource_type(related_object) relation_data.append(OrderedDict([ ('type', related_object_type), ('id', encoding.force_text(related_object.pk)) ])) data.update({ field_name: { 'data': relation_data, 'meta': { 'count': len(relation_data) } } }) continue if isinstance(field, ListSerializer): relation_data = list() serializer_data = resource.get(field_name) resource_instance_queryset = list(relation_instance_or_manager.all()) if isinstance(serializer_data, list): for position in range(len(serializer_data)): nested_resource_instance = resource_instance_queryset[position] nested_resource_instance_type = utils.get_resource_type_from_serializer(field.child) relation_data.append(OrderedDict([ ('type', nested_resource_instance_type), ('id', encoding.force_text(nested_resource_instance.pk)) ])) data.update({field_name: {'data': relation_data}}) continue if isinstance(field, ModelSerializer): data.update({ field_name: { 'data': ( OrderedDict([ ('type', relation_type), ('id', encoding.force_text(relation_instance_or_manager.pk)) ]) if resource.get(field_name) else None) } }) continue return utils.format_keys(data)