Skip to content
Snippets Groups Projects
Commit b6703417 authored by Jorrit Schaap's avatar Jorrit Schaap
Browse files

TMSS-207: generalized serialization of reverse relations, so they are...

TMSS-207: generalized serialization of reverse relations, so they are serialized in _ids lists as well (next to the normal hyperlinks)
parent 856d3d2d
Branches
Tags
1 merge request!175Resolve TMSS-207
...@@ -85,13 +85,11 @@ class DataproductFeedbackTemplateSerializer(RelationalHyperlinkedModelSerializer ...@@ -85,13 +85,11 @@ class DataproductFeedbackTemplateSerializer(RelationalHyperlinkedModelSerializer
class SubtaskSerializer(RelationalHyperlinkedModelSerializer): class SubtaskSerializer(RelationalHyperlinkedModelSerializer):
# If this is OK then we can extend API with NO url ('flat' values) on more places if required # If this is OK then we can extend API with NO url ('flat' values) on more places if required
cluster_value = serializers.StringRelatedField(source='cluster', label='cluster_value', read_only=True) cluster_value = serializers.StringRelatedField(source='cluster', label='cluster_value', read_only=True)
task_blueprint_id = serializers.StringRelatedField(source='task_blueprint', read_only=True)
specifications_template_id = serializers.StringRelatedField(source='specifications_template', read_only=True)
class Meta: class Meta:
model = models.Subtask model = models.Subtask
fields = '__all__' fields = '__all__'
extra_fields = ['cluster_value', 'task_blueprint_id', 'specifications_template_id'] extra_fields = ['cluster_value']
class SubtaskInputSerializer(RelationalHyperlinkedModelSerializer): class SubtaskInputSerializer(RelationalHyperlinkedModelSerializer):
......
...@@ -12,31 +12,61 @@ import json ...@@ -12,31 +12,61 @@ import json
class RelationalHyperlinkedModelSerializer(serializers.HyperlinkedModelSerializer): class RelationalHyperlinkedModelSerializer(serializers.HyperlinkedModelSerializer):
_accepted_pk_names = ('id', 'name')
def get_field_names(self, declared_fields, info): def get_field_names(self, declared_fields, info):
expanded_fields = super().get_field_names(declared_fields, info) expanded_fields = super().get_field_names(declared_fields, info)
# always add the primay key as well, cause it makes parsing in the client so much easier (no 'id' extraction from urls) # always add the primay key as well, cause it makes parsing in the client so much easier (no 'id' extraction from urls)
expanded_fields.insert(0, info.pk.name) expanded_fields.insert(0, info.pk.name)
# always 'plain'-values of the fieldnammes which relate to 'lookup-tables # always add 'plain'-values of the fieldnammes which relate to 'lookup-tables'
expanded_fields += self.get_choice_field_value_names(declared_fields, info) expanded_fields += self.get_choice_field_value_names(declared_fields, info)
# always add 'plain-id'-values of the fieldnammes which to forward_relations
expanded_fields += self.get_forward_relations_field_id_names(declared_fields, info)
# always add 'plain-id'-values of the fieldnammes which to reverse_relations
expanded_fields += self.get_reverse_relations_field_id_names(declared_fields, info)
if getattr(self.Meta, 'extra_fields', None): if getattr(self.Meta, 'extra_fields', None):
return expanded_fields + self.Meta.extra_fields expanded_fields += self.Meta.extra_fields
else:
return expanded_fields # return them sorted alphabetically
return sorted(expanded_fields)
def get_choice_field_value_names(self, declared_fields, model_info): def get_choice_field_value_names(self, declared_fields, model_info):
'''get a list of field_names with '_value' appended for related fields of the "AbstractChoice" type''' '''get a list of field_names with '_value' appended for related fields of the "AbstractChoice" type'''
return [name+'_value' for name, rel in model_info.forward_relations.items() return [name+'_value' for name, rel in model_info.forward_relations.items()
if issubclass(rel.related_model, models.AbstractChoice)] if issubclass(rel.related_model, models.AbstractChoice)]
def get_forward_relations_field_id_names(self, declared_fields, model_info):
'''get a list of field_names with '_id' appended for forward_relation fields'''
return [name+'_id' for name, rel in model_info.forward_relations.items()
if rel.related_model._meta.pk.name in self._accepted_pk_names]
def get_reverse_relations_field_id_names(self, declared_fields, model_info):
'''get a list of field_names with '_ids' appended for reverse_relations fields'''
return [name+'_ids' for name, rel in model_info.reverse_relations.items()
if rel.related_model._meta.pk.name in self._accepted_pk_names]
def build_field(self, field_name, info, model_class, nested_depth): def build_field(self, field_name, info, model_class, nested_depth):
'''override of super.build_field to handle 'choice' fields''' '''override of super.build_field to handle 'choice' fields'''
try: try:
return super().build_field(field_name, info, model_class, nested_depth) return super().build_field(field_name, info, model_class, nested_depth)
except ImproperlyConfigured: except ImproperlyConfigured:
return self.build_choice_field(field_name, info) if field_name.endswith('_ids'):
return self.build_reverse_relations_ids_field(field_name, info, model_class, nested_depth)
if field_name.endswith('_value'):
return self.build_choice_field(field_name, info)
raise
def build_reverse_relations_ids_field(self, field_name, info, model_class, nested_depth):
'''builds a PrimaryKeyRelatedField serializer for the 'reverse_relations_ids' fields'''
return serializers.PrimaryKeyRelatedField, {'label':field_name,
'source':field_name[:-4], # cut '_ids' from end
'many':True,
'read_only':True}
def build_choice_field(self, field_name, info): def build_choice_field(self, field_name, info):
'''builds a StringRelatedField serializer for the 'choice' fields''' '''builds a StringRelatedField serializer for the 'choice' fields'''
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment