def get_field_info(self, field): """ Given an instance of a serializer field, return a dictionary of metadata about it. """ field_info = OrderedDict() serializer = field.parent if isinstance(field, serializers.ManyRelatedField): field_info['type'] = self.type_lookup[field.child_relation] else: field_info['type'] = self.type_lookup[field] try: serializer_model = getattr(serializer.Meta, 'model') field_info['relationship_type'] = self.relation_type_lookup[ getattr(serializer_model, field.field_name) ] except KeyError: pass except AttributeError: pass else: field_info['relationship_resource'] = get_related_resource_type(field) field_info['required'] = getattr(field, 'required', False) attrs = [ 'read_only', 'write_only', 'label', 'help_text', 'min_length', 'max_length', 'min_value', 'max_value', 'initial' ] for attr in attrs: value = getattr(field, attr, None) if value is not None and value != '': field_info[attr] = force_text(value, strings_only=True) if getattr(field, 'child', None): field_info['child'] = self.get_field_info(field.child) elif getattr(field, 'fields', None): field_info['children'] = self.get_serializer_info(field) if ( not field_info.get('read_only') and not field_info.get('relationship_resource') and hasattr(field, 'choices') ): field_info['choices'] = [ { 'value': choice_value, 'display_name': force_text(choice_name, strings_only=True) } for choice_value, choice_name in field.choices.items() ] if hasattr(serializer, 'included_serializers') and 'relationship_resource' in field_info: field_info['allows_include'] = field.field_name in serializer.included_serializers return field_info
def test_m2m_relation(self): """ Ensure m2ms have their types identified correctly. """ serializer = EntrySerializer() field = serializer.fields['authors'] self.assertEqual(utils.get_related_resource_type(field), 'authors')
def test_reverse_relation(self): """ Ensure reverse foreign keys have their types identified correctly. """ serializer = EntrySerializer() field = serializer.fields['comments'] self.assertEqual(utils.get_related_resource_type(field), 'comments')
def get_field_info(self, field): """ Given an instance of a serializer field, return a dictionary of metadata about it. """ field_info = OrderedDict() serializer = field.parent if isinstance(field, serializers.ManyRelatedField): field_info['type'] = self.type_lookup[field.child_relation] else: field_info['type'] = self.type_lookup[field] try: serializer_model = getattr(serializer.Meta, 'model') field_info['relationship_type'] = self.relation_type_lookup[ getattr(serializer_model, field.field_name)] except KeyError: pass except AttributeError: pass else: field_info['relationship_resource'] = get_related_resource_type( field) field_info['required'] = getattr(field, 'required', False) attrs = [ 'read_only', 'write_only', 'label', 'help_text', 'min_length', 'max_length', 'min_value', 'max_value', 'initial' ] for attr in attrs: value = getattr(field, attr, None) if value is not None and value != '': field_info[attr] = force_text(value, strings_only=True) if getattr(field, 'child', None): field_info['child'] = self.get_field_info(field.child) elif getattr(field, 'fields', None): field_info['children'] = self.get_serializer_info(field) if (not field_info.get('read_only') and not field_info.get('relationship_resource') and hasattr(field, 'choices')): field_info['choices'] = [{ 'value': choice_value, 'display_name': force_text(choice_name, strings_only=True) } for choice_value, choice_name in field.choices.items()] if hasattr(serializer, 'included_serializers' ) and 'relationship_resource' in field_info: field_info[ 'allows_include'] = field.field_name in serializer.included_serializers return field_info
def test_get_related_resource_type(model_class, field, output): class RelatedResourceTypeSerializer(serializers.ModelSerializer): class Meta: model = model_class fields = (field,) serializer = RelatedResourceTypeSerializer() field = serializer.fields[field] assert get_related_resource_type(field) == output
def test_get_related_resource_type_from_plain_serializer_class( related_field_kwargs, output): class PlainRelatedResourceTypeSerializer(serializers.Serializer): basic_models = serializers.ResourceRelatedField(many=True, **related_field_kwargs) serializer = PlainRelatedResourceTypeSerializer() field = serializer.fields["basic_models"] assert get_related_resource_type(field) == output
def generate_relationship(self, field): field_schema = openapi.Schema( title='Relationship object', type=openapi.TYPE_OBJECT, properties=utils.OrderedDict(( ('type', openapi.Schema( type=openapi.TYPE_STRING, title='Type of related object', enum=[get_related_resource_type(field)] )), ('id', openapi.Schema( type=openapi.TYPE_STRING, title='ID of related object', )) )) ) return field.field_name, self.decorate_with_data(field_schema)
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)
def get_field_info(self, field): """ Given an instance of a serializer field, return a dictionary of metadata about it. """ field_info = OrderedDict() serializer = field.parent if isinstance(field, serializers.ManyRelatedField): field_info["type"] = self.type_lookup[field.child_relation] else: field_info["type"] = self.type_lookup[field] try: serializer_model = getattr(serializer.Meta, "model") field_info["relationship_type"] = self.relation_type_lookup[ getattr(serializer_model, field.field_name) ] except KeyError: pass except AttributeError: pass else: field_info["relationship_resource"] = get_related_resource_type(field) field_info["required"] = getattr(field, "required", False) attrs = [ "read_only", "write_only", "label", "help_text", "min_length", "max_length", "min_value", "max_value", "initial", ] for attr in attrs: value = getattr(field, attr, None) if value is not None and value != "": field_info[attr] = force_str(value, strings_only=True) if getattr(field, "child", None): field_info["child"] = self.get_field_info(field.child) elif getattr(field, "fields", None): field_info["children"] = self.get_serializer_info(field) if ( not field_info.get("read_only") and not field_info.get("relationship_resource") and hasattr(field, "choices") ): field_info["choices"] = [ { "value": choice_value, "display_name": force_str(choice_name, strings_only=True), } for choice_value, choice_name in field.choices.items() ] if ( hasattr(serializer, "included_serializers") and "relationship_resource" in field_info ): field_info["allows_include"] = ( field.field_name in serializer.included_serializers ) return field_info