class CollectionSerializer(ResolweBaseSerializer): """Serializer for Collection objects.""" settings = ProjectableJSONField(required=False) descriptor = ProjectableJSONField(required=False) descriptor_schema = NestedDescriptorSchemaSerializer(required=False) class Meta: """CollectionSerializer Meta options.""" model = Collection read_only_fields = ( 'created', 'descriptor_dirty', 'id', 'modified', ) update_protected_fields = ('contributor', ) fields = read_only_fields + update_protected_fields + ( 'data', 'description', 'descriptor', 'descriptor_schema', 'name', 'settings', 'slug', ) def _serialize_data(self, data): """Return serialized data or list of ids, depending on `hydrate_data` query param.""" if self.request and self.request.query_params.get( 'hydrate_data', False): serializer = DataSerializer(data, many=True, read_only=True) serializer.bind('data', self) return serializer.data else: return [d.id for d in data] def _filter_queryset(self, perms, queryset): """Filter object objects by permissions of user in request.""" user = self.request.user if self.request else AnonymousUser() return get_objects_for_user(user, perms, queryset) def get_data(self, collection): """Return serialized list of data objects on collection that user has `view` permission on.""" data = self._filter_queryset('view_data', collection.data.all()) return self._serialize_data(data) def get_fields(self): """Dynamically adapt fields based on the current request.""" fields = super(CollectionSerializer, self).get_fields() if self.request.method == "GET": fields['data'] = serializers.SerializerMethodField() else: fields['data'] = serializers.PrimaryKeyRelatedField(many=True, read_only=True) return fields
class CollectionSerializer(ResolweBaseSerializer): """Serializer for Collection objects.""" settings = ProjectableJSONField(required=False) descriptor = ProjectableJSONField(required=False) descriptor_schema = DictRelatedField( queryset=DescriptorSchema.objects.all(), serializer=DescriptorSchemaSerializer, allow_null=True, required=False, ) class Meta: """CollectionSerializer Meta options.""" model = Collection read_only_fields = ( 'created', 'descriptor_dirty', 'duplicated', 'id', 'modified', ) update_protected_fields = ('contributor', ) fields = read_only_fields + update_protected_fields + ( 'description', 'descriptor', 'descriptor_schema', 'name', 'settings', 'slug', 'tags', )
class DataSerializer(ResolweBaseSerializer): """Serializer for Data objects.""" input = ProjectableJSONField(required=False) output = ProjectableJSONField(required=False) descriptor = ProjectableJSONField(required=False) process_slug = serializers.CharField(source='process.slug', read_only=True) process_name = serializers.CharField(source='process.name', read_only=True) process_type = serializers.CharField(source='process.type', read_only=True) process_input_schema = ProjectableJSONField(source='process.input_schema', read_only=True) process_output_schema = ProjectableJSONField(source='process.output_schema', read_only=True) process = ResolweSlugRelatedField(queryset=Process.objects.all()) descriptor_schema = NestedDescriptorSchemaSerializer(required=False) class Meta: """DataSerializer Meta options.""" model = Data read_only_fields = ( 'checksum', 'created', 'descriptor_dirty', 'finished', 'id', 'modified', 'process_cores', 'process_error', 'process_info', 'process_input_schema', 'process_memory', 'process_name', 'process_output_schema', 'process_progress', 'process_rc', 'process_slug', 'process_type', 'process_warning', 'output', 'size', 'started', 'status', ) update_protected_fields = ( 'contributor', 'input', 'process', ) fields = read_only_fields + update_protected_fields + ( 'descriptor', 'descriptor_schema', 'name', 'slug', 'tags', )
class PositionInRelationSerializer(SelectiveFieldMixin, serializers.ModelSerializer): """Serializer for PositionInRelation objects.""" position = ProjectableJSONField(allow_null=True, required=False) class Meta: """PositionInRelationSerializer Meta options.""" model = PositionInRelation fields = ('entity', 'position')
class StorageSerializer(ResolweBaseSerializer): """Serializer for Storage objects.""" json = ProjectableJSONField() class Meta: """StorageSerializer Meta options.""" model = Storage update_protected_fields = ('contributor', ) read_only_fields = ('id', 'created', 'modified') fields = ('slug', 'name', 'data', 'json') + update_protected_fields + read_only_fields
class DescriptorSchemaSerializer(ResolweBaseSerializer): """Serializer for DescriptorSchema objects.""" schema = ProjectableJSONField(required=False) class Meta: """TemplateSerializer Meta options.""" model = DescriptorSchema update_protected_fields = ('contributor', ) read_only_fields = ('id', 'created', 'modified') fields = ('slug', 'name', 'version', 'schema') + update_protected_fields + read_only_fields
class DataSerializer(ResolweBaseSerializer): """Serializer for Data objects.""" input = ProjectableJSONField(required=False) output = ProjectableJSONField(required=False) descriptor = ProjectableJSONField(required=False) process_name = serializers.CharField(source='process.name', read_only=True) process_type = serializers.CharField(source='process.type', read_only=True) process_input_schema = ProjectableJSONField(source='process.input_schema', read_only=True) process_output_schema = ProjectableJSONField(source='process.output_schema', read_only=True) name = serializers.CharField(read_only=False, required=False) slug = serializers.CharField(read_only=False, required=False) class Meta: """DataSerializer Meta options.""" model = Data update_protected_fields = ('contributor', 'process',) read_only_fields = ('id', 'created', 'modified', 'started', 'finished', 'checksum', 'status', 'process_progress', 'process_rc', 'process_info', 'process_warning', 'process_error', 'process_type', 'process_input_schema', 'process_output_schema', 'process_name', 'descriptor_dirty') fields = ('slug', 'name', 'contributor', 'input', 'output', 'descriptor_schema', 'descriptor', 'tags') + update_protected_fields + read_only_fields def get_fields(self): """Dynamically adapt fields based on the current request.""" fields = super(DataSerializer, self).get_fields() if self.request.method == "GET": fields['descriptor_schema'] = DescriptorSchemaSerializer(required=False) else: fields['descriptor_schema'] = serializers.PrimaryKeyRelatedField( queryset=DescriptorSchema.objects.all(), required=False ) return fields
class CollectionSerializer(ResolweBaseSerializer): """Serializer for Collection objects.""" settings = ProjectableJSONField(required=False) descriptor = ProjectableJSONField(required=False) descriptor_schema = DictRelatedField( queryset=DescriptorSchema.objects.all(), serializer=DescriptorSchemaSerializer, allow_null=True, required=False, ) class Meta: """CollectionSerializer Meta options.""" model = Collection read_only_fields = ( "created", "descriptor_dirty", "duplicated", "id", "modified", ) update_protected_fields = ("contributor",) fields = ( read_only_fields + update_protected_fields + ( "description", "descriptor", "descriptor_schema", "name", "settings", "slug", "tags", ) )
class StorageSerializer(ResolweBaseSerializer): """Serializer for Storage objects.""" json = ProjectableJSONField() class Meta: """StorageSerializer Meta options.""" model = Storage read_only_fields = ( "created", "id", "modified", ) update_protected_fields = ("contributor", ) fields = (read_only_fields + update_protected_fields + ( "data", "json", "name", "slug", ))
class DescriptorSchemaSerializer(ResolweBaseSerializer): """Serializer for DescriptorSchema objects.""" schema = ProjectableJSONField(required=False) class Meta: """DescriptorSchemaSerializer Meta options.""" model = DescriptorSchema read_only_fields = ( "created", "id", "modified", ) update_protected_fields = ( "contributor", "version", ) fields = ( read_only_fields + update_protected_fields + ("description", "name", "schema", "slug",) )
class DataSerializer(ResolweBaseSerializer): """Serializer for Data objects.""" input = ProjectableJSONField(required=False) output = ProjectableJSONField(required=False) descriptor = ProjectableJSONField(required=False) process = DictRelatedField(queryset=Process.objects.all(), serializer=ProcessSerializer) descriptor_schema = DictRelatedField( queryset=DescriptorSchema.objects.all(), serializer=DescriptorSchemaSerializer, allow_null=True, required=False, ) collection = DictRelatedField( queryset=Collection.objects.all(), serializer=CollectionSerializer, allow_null=True, required=False, write_permission="edit", ) entity = DictRelatedField( queryset=Entity.objects.all(), serializer=EntitySerializer, allow_null=True, required=False, write_permission="edit", ) class Meta: """DataSerializer Meta options.""" model = Data read_only_fields = ( "checksum", "created", "descriptor_dirty", "duplicated", "finished", "id", "modified", "process_cores", "process_error", "process_info", "process_memory", "process_progress", "process_rc", "process_warning", "output", "scheduled", "size", "started", "status", ) update_protected_fields = ( "contributor", "input", "process", ) fields = (read_only_fields + update_protected_fields + ( "collection", "descriptor", "descriptor_schema", "entity", "name", "slug", "tags", )) def validate_process(self, process): """Check that process is active.""" if not process.is_active: raise serializers.ValidationError( "Process {} is not active.".format(process)) return process def validate_collection(self, collection): """Verify that changing collection is done in the right place.""" if getattr(self.instance, "entity", None): if getattr(self.instance.entity.collection, "id", None) != getattr( collection, "id", None): raise serializers.ValidationError( "If Data is in entity, you can only move it to another collection " "by moving entire entity.") return collection
class BaseCollectionSerializer(ResolweBaseSerializer): """Base serializer for Collection objects.""" settings = ProjectableJSONField(required=False) descriptor = ProjectableJSONField(required=False) descriptor_schema = DictRelatedField( queryset=DescriptorSchema.objects.all(), serializer=DescriptorSchemaSerializer, allow_null=True, required=False, ) data_count = serializers.SerializerMethodField(required=False) status = serializers.SerializerMethodField(required=False) def get_data_count(self, collection): """Return number of data objects on the collection.""" return collection.data.count() def get_status(self, collection): """Return status of the collection based on the status of data objects.""" status_set = set([data.status for data in collection.data.all()]) if not status_set: return None status_order = [ Data.STATUS_ERROR, Data.STATUS_UPLOADING, Data.STATUS_PROCESSING, Data.STATUS_PREPARING, Data.STATUS_WAITING, Data.STATUS_RESOLVING, Data.STATUS_DONE, ] for status in status_order: if status in status_set: return status logger.warning( "Could not determine the status of a collection.", extra={"collection": collection.__dict__}, ) return None class Meta: """CollectionSerializer Meta options.""" model = Collection read_only_fields = ( "created", "descriptor_dirty", "duplicated", "id", "modified", "data_count", "status", ) update_protected_fields = ("contributor", ) fields = (read_only_fields + update_protected_fields + ( "description", "descriptor", "descriptor_schema", "name", "settings", "slug", "tags", ))
class DataSerializer(ResolweBaseSerializer): """Serializer for Data objects.""" input = ProjectableJSONField(required=False) output = ProjectableJSONField(required=False) descriptor = ProjectableJSONField(required=False) process_slug = serializers.CharField(source='process.slug', read_only=True) process_name = serializers.CharField(source='process.name', read_only=True) process_type = serializers.CharField(source='process.type', read_only=True) process_input_schema = ProjectableJSONField(source='process.input_schema', read_only=True) process_output_schema = ProjectableJSONField( source='process.output_schema', read_only=True) process = ResolweSlugRelatedField(queryset=Process.objects.all()) descriptor_schema = NestedDescriptorSchemaSerializer(required=False) collections = serializers.SerializerMethodField() entities = serializers.SerializerMethodField() class Meta: """DataSerializer Meta options.""" model = Data read_only_fields = ( 'checksum', 'created', 'descriptor_dirty', 'finished', 'id', 'modified', 'process_cores', 'process_error', 'process_info', 'process_input_schema', 'process_memory', 'process_name', 'process_output_schema', 'process_progress', 'process_rc', 'process_slug', 'process_type', 'process_warning', 'output', 'scheduled', 'size', 'started', 'status', ) update_protected_fields = ( 'contributor', 'input', 'process', 'collections', 'entities', ) fields = read_only_fields + update_protected_fields + ( 'descriptor', 'descriptor_schema', 'name', 'slug', 'tags', ) def _serialize_items(self, serializer, kind, items): """Return serialized items or list of ids, depending on `hydrate_XXX` query param.""" if self.request and self.request.query_params.get( 'hydrate_{}'.format(kind), False): serializer = serializer(items, many=True, read_only=True) serializer.bind(kind, self) return serializer.data else: return [item.id for item in items] def _filter_queryset(self, perms, queryset): """Filter object objects by permissions of user in request.""" user = self.request.user if self.request else AnonymousUser() return get_objects_for_user(user, perms, queryset) def get_collections(self, data): """Return serialized list of collection objects on data that user has `view` permission on.""" collections = self._filter_queryset('view_collection', data.collection_set.all()) from .collection import CollectionSerializer class CollectionWithoutDataSerializer(WithoutDataSerializerMixin, CollectionSerializer): """Collection without data field serializer.""" pass return self._serialize_items(CollectionWithoutDataSerializer, 'collections', collections) def get_entities(self, data): """Return serialized list of entity objects on data that user has `view` permission on.""" entities = self._filter_queryset('view_entity', data.entity_set.all()) from .entity import EntitySerializer class EntityWithoutDataSerializer(WithoutDataSerializerMixin, EntitySerializer): """Entity without data field serializer.""" pass return self._serialize_items(EntityWithoutDataSerializer, 'entities', entities) def get_fields(self): """Dynamically adapt fields based on the current request.""" fields = super(DataSerializer, self).get_fields() # Hide collections/entities fields on list views as fetching them may be expensive. if self.parent is not None: del fields['collections'] del fields['entities'] return fields
class DataSerializer(ResolweBaseSerializer): """Serializer for Data objects.""" input = ProjectableJSONField(required=False) output = ProjectableJSONField(required=False) descriptor = ProjectableJSONField(required=False) process_resources = ProjectableJSONField(required=False) process = DictRelatedField( queryset=Process.objects.all(), serializer=ProcessSerializer ) descriptor_schema = DictRelatedField( queryset=DescriptorSchema.objects.all(), serializer=DescriptorSchemaSerializer, allow_null=True, required=False, ) collection = DictRelatedField( queryset=Collection.objects.all(), serializer=CollectionSerializer, allow_null=True, required=False, write_permission=Permission.EDIT, ) entity = DictRelatedField( queryset=Entity.objects.all(), serializer=EntitySerializer, allow_null=True, required=False, write_permission=Permission.EDIT, ) class Meta: """DataSerializer Meta options.""" model = Data read_only_fields = ( "checksum", "created", "descriptor_dirty", "duplicated", "finished", "id", "modified", "process_cores", "process_error", "process_info", "process_memory", "process_progress", "process_rc", "process_warning", "output", "scheduled", "size", "started", "status", ) update_protected_fields = ( "contributor", "input", "process", ) fields = ( read_only_fields + update_protected_fields + ( "collection", "descriptor", "descriptor_schema", "entity", "name", "slug", "tags", "process_resources", ) ) def validate_process(self, process): """Check that process is active.""" if not process.is_active: raise serializers.ValidationError( "Process {} is not active.".format(process) ) return process def validate_collection(self, collection): """Verify that changing collection is done in the right place.""" if self.instance and self.instance.collection != collection: self.instance.validate_change_collection(collection) return collection @transaction.atomic def update(self, instance, validated_data): """Update.""" update_collection = "collection" in validated_data new_collection = validated_data.pop("collection", None) instance = super().update(instance, validated_data) if update_collection and new_collection != instance.collection: instance.move_to_collection(new_collection) return instance