def extract_relationships(cls, fields, resource, resource_instance): """ Builds the relationships top level object based on related serializers. """ # 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 iter(fields.items()): # Skip URL field if field_name == api_settings.URL_FIELD_NAME: continue # don't output a key for write only fields if fields[field_name].write_only: continue # Skip fields without relations if not utils.is_relationship_field(field): continue source = field.source relation_type = utils.get_related_resource_type(field) if isinstance(field, relations.HyperlinkedIdentityField): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent) if not resolved: continue # special case for HyperlinkedIdentityField relation_data = list() # Don't try to query an empty relation relation_queryset = (relation_instance if relation_instance is not None else list()) for related_object in relation_queryset: relation_data.append( OrderedDict([ ("type", relation_type), ("id", encoding.force_str(related_object.pk)), ])) data.update({ field_name: { "links": { "related": resource.get(field_name) }, "data": relation_data, "meta": { "count": len(relation_data) }, } }) continue relation_data = {} if isinstance(field, HyperlinkedMixin): field_links = field.get_links(resource_instance, field.related_link_lookup_field) relation_data.update( {"links": field_links} if field_links else dict()) data.update({field_name: relation_data}) if isinstance(field, (ResourceRelatedField, )): if not isinstance(field, SkipDataMixin): relation_data.update({"data": resource.get(field_name)}) data.update({field_name: relation_data}) continue if isinstance( field, (relations.PrimaryKeyRelatedField, relations.HyperlinkedRelatedField), ): resolved, relation = utils.get_relation_instance( resource_instance, "%s_id" % source, field.parent) if not resolved: continue relation_id = relation if resource.get(field_name) else None relation_data = { "data": (OrderedDict([ ("type", relation_type), ("id", encoding.force_str(relation_id)), ]) if relation_id is not None else None) } if isinstance(field, relations.HyperlinkedRelatedField ) and resource.get(field_name): relation_data.update( {"links": { "related": resource.get(field_name) }}) data.update({field_name: relation_data}) continue if isinstance(field, relations.ManyRelatedField): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent) if not resolved: continue relation_data = {} if isinstance(resource.get(field_name), Iterable): relation_data.update( {"meta": { "count": len(resource.get(field_name)) }}) if isinstance(field.child_relation, ResourceRelatedField): # special case for ResourceRelatedField relation_data.update({"data": resource.get(field_name)}) if isinstance(field.child_relation, HyperlinkedMixin): field_links = field.child_relation.get_links( resource_instance, field.child_relation.related_link_lookup_field, ) relation_data.update( {"links": field_links} if field_links else dict()) data.update({field_name: relation_data}) continue relation_data = list() for nested_resource_instance in relation_instance: nested_resource_instance_type = ( relation_type or utils.get_resource_type_from_instance( nested_resource_instance)) relation_data.append( OrderedDict([ ("type", nested_resource_instance_type), ("id", encoding.force_str(nested_resource_instance.pk)), ])) data.update({ field_name: { "data": relation_data, "meta": { "count": len(relation_data) }, } }) continue return utils.format_field_names(data)
def extract_relationships(cls, fields, resource, resource_instance): """ Builds the relationships top level object based on related serializers. """ # Avoid circular deps from rest_framework_json_api.relations import ResourceRelatedField data = OrderedDict() render_nested_as_attribute = json_api_settings.SERIALIZE_NESTED_SERIALIZERS_AS_ATTRIBUTE # Don't try to extract relationships from a non-existent resource if resource_instance is None: return for field_name, field in iter(fields.items()): # Skip URL field if field_name == api_settings.URL_FIELD_NAME: continue # don't output a key for write only fields if fields[field_name].write_only: continue # Skip fields without relations if not isinstance(field, (relations.RelatedField, relations.ManyRelatedField, BaseSerializer)): continue if isinstance(field, BaseSerializer) and render_nested_as_attribute: continue source = field.source relation_type = utils.get_related_resource_type(field) if isinstance(field, relations.HyperlinkedIdentityField): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent) if not resolved: continue # special case for HyperlinkedIdentityField relation_data = list() # Don't try to query an empty relation relation_queryset = relation_instance \ if relation_instance is not None else list() for related_object in relation_queryset: relation_data.append( OrderedDict([('type', relation_type), ('id', encoding.force_str(related_object.pk))])) data.update({ field_name: { 'links': { "related": resource.get(field_name) }, 'data': relation_data, 'meta': { 'count': len(relation_data) } } }) continue relation_data = {} if isinstance(field, HyperlinkedMixin): field_links = field.get_links(resource_instance, field.related_link_lookup_field) relation_data.update( {'links': field_links} if field_links else dict()) data.update({field_name: relation_data}) if isinstance(field, (ResourceRelatedField, )): if not isinstance(field, SkipDataMixin): relation_data.update({'data': resource.get(field_name)}) data.update({field_name: relation_data}) continue if isinstance(field, (relations.PrimaryKeyRelatedField, relations.HyperlinkedRelatedField)): resolved, relation = utils.get_relation_instance( resource_instance, '%s_id' % source, field.parent) if not resolved: continue relation_id = relation if resource.get(field_name) else None relation_data = { 'data': (OrderedDict([('type', relation_type), ('id', encoding.force_str(relation_id))]) if relation_id is not None else None) } if (isinstance(field, relations.HyperlinkedRelatedField) and resource.get(field_name)): relation_data.update( {'links': { 'related': resource.get(field_name) }}) data.update({field_name: relation_data}) continue if isinstance(field, relations.ManyRelatedField): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent) if not resolved: continue relation_data = {} if isinstance(resource.get(field_name), Iterable): relation_data.update( {'meta': { 'count': len(resource.get(field_name)) }}) if isinstance(field.child_relation, ResourceRelatedField): # special case for ResourceRelatedField relation_data.update({'data': resource.get(field_name)}) if isinstance(field.child_relation, HyperlinkedMixin): field_links = field.child_relation.get_links( resource_instance, field.child_relation.related_link_lookup_field) relation_data.update( {'links': field_links} if field_links else dict()) data.update({field_name: relation_data}) continue relation_data = list() for nested_resource_instance in relation_instance: nested_resource_instance_type = ( relation_type or utils.get_resource_type_from_instance( nested_resource_instance)) relation_data.append( OrderedDict([ ('type', nested_resource_instance_type), ('id', encoding.force_str(nested_resource_instance.pk)) ])) data.update({ field_name: { 'data': relation_data, 'meta': { 'count': len(relation_data) } } }) continue if isinstance(field, ListSerializer): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent) if not resolved: continue relation_data = list() serializer_data = resource.get(field_name) resource_instance_queryset = list(relation_instance) if isinstance(serializer_data, list): for position in range(len(serializer_data)): nested_resource_instance = resource_instance_queryset[ position] nested_resource_instance_type = ( relation_type or utils.get_resource_type_from_instance( nested_resource_instance)) relation_data.append( OrderedDict([('type', nested_resource_instance_type), ('id', encoding.force_str( nested_resource_instance.pk))])) data.update({field_name: {'data': relation_data}}) continue if isinstance(field, Serializer): relation_instance_id = getattr(resource_instance, source + "_id", None) if not relation_instance_id: resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent) if not resolved: continue if relation_instance is not None: relation_instance_id = relation_instance.pk data.update({ field_name: { 'data': (OrderedDict([ ('type', relation_type), ('id', encoding.force_str(relation_instance_id)) ]) if resource.get(field_name) else None) } }) continue return utils.format_field_names(data)
def extract_relationships(cls, 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 relation_type = utils.get_related_resource_type(field) if isinstance(field, relations.HyperlinkedIdentityField): resolved, relation_instance = utils.get_relation_instance(resource_instance, source, field.parent) if not resolved: continue # special case for HyperlinkedIdentityField relation_data = list() # Don't try to query an empty relation relation_queryset = relation_instance \ if relation_instance 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': cls.encode_ids(relation_data), 'meta': { 'count': len(relation_data) } }}) continue if isinstance(field, ResourceRelatedField): resolved, relation_instance = utils.get_relation_instance(resource_instance, source, field.parent) if not resolved: continue # special case for ResourceRelatedField relation_data = { 'data': cls.encode_ids(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)): resolved, relation = utils.get_relation_instance(resource_instance, '%s_id' % source, field.parent) if not resolved: continue relation_id = relation if resource.get(field_name) else None relation_data = { 'data': ( OrderedDict([('type', relation_type), ('id', cls.encode_id(relation_id, relation_type))]) 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): resolved, relation_instance = utils.get_relation_instance(resource_instance, source, field.parent) if not resolved: continue if isinstance(field.child_relation, ResourceRelatedField): # special case for ResourceRelatedField relation_data = { 'data': cls.encode_ids(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 nested_resource_instance in relation_instance: nested_resource_instance_type = ( relation_type or utils.get_resource_type_from_instance(nested_resource_instance) ) relation_data.append(OrderedDict([ ('type', nested_resource_instance_type), ('id', encoding.force_text(nested_resource_instance.pk)) ])) data.update({ field_name: { 'data': cls.encode_ids(relation_data), 'meta': { 'count': len(relation_data) } } }) continue if isinstance(field, ListSerializer): resolved, relation_instance = utils.get_relation_instance(resource_instance, source, field.parent) if not resolved: continue relation_data = list() serializer_data = resource.get(field_name) resource_instance_queryset = list(relation_instance) if isinstance(serializer_data, list): for position in range(len(serializer_data)): nested_resource_instance = resource_instance_queryset[position] nested_resource_instance_type = ( relation_type or utils.get_resource_type_from_instance(nested_resource_instance) ) relation_data.append(OrderedDict([ ('type', nested_resource_instance_type), ('id', encoding.force_text(nested_resource_instance.pk)) ])) data.update({field_name: {'data': cls.encode_ids(relation_data)}}) continue if isinstance(field, Serializer): resolved, relation_instance = utils.get_relation_instance(resource_instance, source, field.parent) if not resolved: continue data.update({ field_name: { 'data': ( OrderedDict([ ('type', relation_type), ('id', cls.encode_id(resource_instance.pk, relation_type)) ]) if resource.get(field_name) else None) } }) continue return utils.format_keys(data)
def extract_relationships(cls, 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 relation_type = utils.get_related_resource_type(field) if isinstance(field, relations.HyperlinkedIdentityField): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent) if not resolved: continue # special case for HyperlinkedIdentityField relation_data = list() # Don't try to query an empty relation relation_queryset = relation_instance \ if relation_instance 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': cls.encode_ids(relation_data), 'meta': { 'count': len(relation_data) } } }) continue if isinstance(field, ResourceRelatedField): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent) if not resolved: continue # special case for ResourceRelatedField relation_data = { 'data': cls.encode_ids(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)): resolved, relation = utils.get_relation_instance( resource_instance, '%s_id' % source, field.parent) if not resolved: continue relation_id = relation if resource.get(field_name) else None relation_data = { 'data': (OrderedDict([ ('type', relation_type), ('id', cls.encode_id(relation_id, relation_type)) ]) 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): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent) if not resolved: continue if isinstance(field.child_relation, ResourceRelatedField): # special case for ResourceRelatedField relation_data = { 'data': cls.encode_ids(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 nested_resource_instance in relation_instance: nested_resource_instance_type = ( relation_type or utils.get_resource_type_from_instance( nested_resource_instance)) relation_data.append( OrderedDict([ ('type', nested_resource_instance_type), ('id', encoding.force_text(nested_resource_instance.pk)) ])) data.update({ field_name: { 'data': cls.encode_ids(relation_data), 'meta': { 'count': len(relation_data) } } }) continue if isinstance(field, ListSerializer): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent) if not resolved: continue relation_data = list() serializer_data = resource.get(field_name) resource_instance_queryset = list(relation_instance) if isinstance(serializer_data, list): for position in range(len(serializer_data)): nested_resource_instance = resource_instance_queryset[ position] nested_resource_instance_type = ( relation_type or utils.get_resource_type_from_instance( nested_resource_instance)) relation_data.append( OrderedDict([('type', nested_resource_instance_type), ('id', encoding.force_text( nested_resource_instance.pk))])) data.update( {field_name: { 'data': cls.encode_ids(relation_data) }}) continue if isinstance(field, Serializer): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent) if not resolved: continue data.update({ field_name: { 'data': (OrderedDict([('type', relation_type), ('id', cls.encode_id(resource_instance.pk, relation_type))]) if resource.get(field_name) else None) } }) continue return utils.format_keys(data)
def extract_relationships(cls, fields, resource, resource_instance): """ Builds the relationships top level object based on related serializers. """ # 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 # don't output a key for write only fields if fields[field_name].write_only: continue # Skip fields without relations if not isinstance( field, (relations.RelatedField, relations.ManyRelatedField, BaseSerializer) ): continue source = field.source relation_type = utils.get_related_resource_type(field) if isinstance(field, relations.HyperlinkedIdentityField): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent ) if not resolved: continue # special case for HyperlinkedIdentityField relation_data = list() # Don't try to query an empty relation relation_queryset = relation_instance \ if relation_instance 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 relation_data = {} if isinstance(field, HyperlinkedMixin): field_links = field.get_links(resource_instance, field.related_link_lookup_field) relation_data.update({'links': field_links} if field_links else dict()) data.update({field_name: relation_data}) if isinstance(field, (ResourceRelatedField, )): if not isinstance(field, SkipDataMixin): relation_data.update({'data': resource.get(field_name)}) data.update({field_name: relation_data}) continue if isinstance( field, (relations.PrimaryKeyRelatedField, relations.HyperlinkedRelatedField) ): resolved, relation = utils.get_relation_instance( resource_instance, '%s_id' % source, field.parent ) if not resolved: continue relation_id = relation if resource.get(field_name) else None relation_data = { 'data': ( OrderedDict([ ('type', relation_type), ('id', encoding.force_text(relation_id)) ]) if relation_id is not None else None) } if ( isinstance(field, relations.HyperlinkedRelatedField) and resource.get(field_name) ): relation_data.update( { 'links': { 'related': resource.get(field_name) } } ) data.update({field_name: relation_data}) continue if isinstance(field, relations.ManyRelatedField): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent ) if not resolved: continue relation_data = {} if isinstance(resource.get(field_name), collections_abc.Iterable): relation_data.update( { 'meta': {'count': len(resource.get(field_name))} } ) if isinstance(field.child_relation, ResourceRelatedField): # special case for ResourceRelatedField relation_data.update( {'data': resource.get(field_name)} ) if isinstance(field.child_relation, HyperlinkedMixin): field_links = field.child_relation.get_links( resource_instance, field.child_relation.related_link_lookup_field ) relation_data.update( {'links': field_links} if field_links else dict() ) data.update({field_name: relation_data}) continue relation_data = list() for nested_resource_instance in relation_instance: nested_resource_instance_type = ( relation_type or utils.get_resource_type_from_instance(nested_resource_instance) ) relation_data.append(OrderedDict([ ('type', nested_resource_instance_type), ('id', encoding.force_text(nested_resource_instance.pk)) ])) data.update({ field_name: { 'data': relation_data, 'meta': { 'count': len(relation_data) } } }) continue if isinstance(field, ListSerializer): resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent ) if not resolved: continue relation_data = list() serializer_data = resource.get(field_name) resource_instance_queryset = list(relation_instance) if isinstance(serializer_data, list): for position in range(len(serializer_data)): nested_resource_instance = resource_instance_queryset[position] nested_resource_instance_type = ( relation_type or utils.get_resource_type_from_instance(nested_resource_instance) ) 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, Serializer): relation_instance_id = getattr(resource_instance, source + "_id", None) if not relation_instance_id: resolved, relation_instance = utils.get_relation_instance( resource_instance, source, field.parent ) if not resolved: continue if relation_instance is not None: relation_instance_id = relation_instance.pk data.update({ field_name: { 'data': ( OrderedDict([ ('type', relation_type), ('id', encoding.force_text(relation_instance_id)) ]) if resource.get(field_name) else None) } }) continue return utils._format_object(data)