diff --git a/SAS/TMSS/src/tmss/tmssapp/serializers/scheduling.py b/SAS/TMSS/src/tmss/tmssapp/serializers/scheduling.py index 69857eb274ed1b0533cedbe5869540ef5b9d8d02..94019765c36ca379d2325784eb48d2751bde5a4c 100644 --- a/SAS/TMSS/src/tmss/tmssapp/serializers/scheduling.py +++ b/SAS/TMSS/src/tmss/tmssapp/serializers/scheduling.py @@ -85,13 +85,11 @@ class DataproductFeedbackTemplateSerializer(RelationalHyperlinkedModelSerializer class SubtaskSerializer(RelationalHyperlinkedModelSerializer): # 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) - task_blueprint_id = serializers.StringRelatedField(source='task_blueprint', read_only=True) - specifications_template_id = serializers.StringRelatedField(source='specifications_template', read_only=True) class Meta: model = models.Subtask fields = '__all__' - extra_fields = ['cluster_value', 'task_blueprint_id', 'specifications_template_id'] + extra_fields = ['cluster_value'] class SubtaskInputSerializer(RelationalHyperlinkedModelSerializer): diff --git a/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py b/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py index d0bfcec81f9045dbfb45e173b58536cc171856d6..4d1ae4d3b271419fcddc417a1025045c6afca4c4 100644 --- a/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py +++ b/SAS/TMSS/src/tmss/tmssapp/serializers/specification.py @@ -12,31 +12,61 @@ import json class RelationalHyperlinkedModelSerializer(serializers.HyperlinkedModelSerializer): + _accepted_pk_names = ('id', 'name') + def get_field_names(self, 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) 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) + # 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): - return expanded_fields + self.Meta.extra_fields - else: - return expanded_fields + expanded_fields += self.Meta.extra_fields + + # return them sorted alphabetically + return sorted(expanded_fields) 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''' return [name+'_value' for name, rel in model_info.forward_relations.items() 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): '''override of super.build_field to handle 'choice' fields''' try: return super().build_field(field_name, info, model_class, nested_depth) 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): '''builds a StringRelatedField serializer for the 'choice' fields'''