class UploadedFileSerializer(serializers.HyperlinkedModelSerializer): owner = serializers.HyperlinkedRelatedField(view_name='user-detail', read_only=True) file_resource = ItemLinkField('_get_file_link') fname = serializers.FileField(write_only=True) upload_path = serializers.CharField() class Meta: model = UploadedFile fields = ('url', 'upload_path', 'fname', 'file_resource', 'owner') @collection_serializer_is_valid def is_valid(self, raise_exception=False): """ Overriden to generate a properly formatted message for validation errors """ return super(UploadedFileSerializer, self).is_valid(raise_exception=raise_exception) def _get_file_link(self, obj): """ Custom method to get the hyperlink to the actual file resource """ fields = self.fields.items() # get the current url url_field = [v for (k, v) in fields if k == 'url'][0] view = url_field.view_name request = self.context['request'] format = self.context['format'] url = url_field.get_url(obj, view, request, format) # return url = current url + file name return url + os.path.basename(obj.fname.name) def validate_file_upload_path(self, user, path): """ Custom method to check that the provided path is unique for this user in the DB. """ # remove leading and trailing slashes path = path.strip('/') if not path: raise serializers.ValidationError({'detail': "Invalid file path!"}) path = os.path.join('/', path) try: # check if path for this file already exists in the db UploadedFile.objects.get(owner=user.id, upload_path=path) except ObjectDoesNotExist: return path else: raise serializers.ValidationError( {'detail': "File already exists!"})
class PluginInstanceFileSerializer(serializers.HyperlinkedModelSerializer): plugin_inst = serializers.HyperlinkedRelatedField( view_name='plugininstance-detail', read_only=True) file_resource = ItemLinkField('get_file_link') fname = serializers.FileField(use_url=False) feed_id = serializers.ReadOnlyField(source='plugin_inst.feed.id') plugin_inst_id = serializers.ReadOnlyField(source='plugin_inst.id') class Meta: model = PluginInstanceFile fields = ('url', 'id', 'creation_date', 'fname', 'feed_id', 'plugin_inst_id', 'file_resource', 'plugin_inst') def get_file_link(self, obj): """ Custom method to get the hyperlink to the actual file resource. """ return get_file_resource_link(self, obj)
class GenericDefaultPipingParameterSerializer( serializers.HyperlinkedModelSerializer): previous_plugin_piping_id = serializers.ReadOnlyField( source='plugin_piping.previous_id') plugin_piping_id = serializers.ReadOnlyField(source='plugin_piping.id') plugin_id = serializers.ReadOnlyField(source='plugin_piping.plugin_id') plugin_name = serializers.ReadOnlyField( source='plugin_param.plugin.meta.name') plugin_version = serializers.ReadOnlyField( source='plugin_param.plugin.version') param_id = serializers.ReadOnlyField(source='plugin_param.id') param_name = serializers.ReadOnlyField(source='plugin_param.name') type = serializers.ReadOnlyField(source='plugin_param.type') value = serializers.SerializerMethodField() url = ItemLinkField('_get_url') plugin_piping = serializers.HyperlinkedRelatedField( view_name='pluginpiping-detail', read_only=True) plugin_param = serializers.HyperlinkedRelatedField( view_name='pluginparameter-detail', read_only=True) class Meta: model = DefaultPipingStrParameter fields = ('url', 'id', 'value', 'type', 'plugin_piping_id', 'previous_plugin_piping_id', 'param_name', 'param_id', 'plugin_piping', 'plugin_name', 'plugin_version', 'plugin_id', 'plugin_param') def _get_url(self, obj): """ Custom method to get the correct url for the serialized object regardless of its type. """ request = self.context['request'] # here default piping parameter detail view names are assumed to # follow a convention view_name = 'defaultpiping' + TYPES[ obj.plugin_param.type] + 'parameter-detail' return reverse(view_name, request=request, kwargs={"pk": obj.id}) def get_value(self, obj): """ Overriden to get the default parameter value regardless of its type. """ return obj.value
class UploadedFileSerializer(serializers.HyperlinkedModelSerializer): owner = serializers.HyperlinkedRelatedField(view_name='user-detail', read_only=True) file_resource = ItemLinkField('get_file_link') fname = serializers.FileField(use_url=False) fsize = serializers.ReadOnlyField(source='fname.size') upload_path = serializers.CharField(write_only=True) class Meta: model = UploadedFile fields = ('url', 'id', 'creation_date', 'upload_path', 'fname', 'fsize', 'file_resource', 'owner') def get_file_link(self, obj): """ Custom method to get the hyperlink to the actual file resource. """ return get_file_resource_link(self, obj) def validate_upload_path(self, upload_path): """ Overriden to check whether the provided path is under <username>/<uploads>/. """ # remove leading and trailing slashes upload_path = upload_path.strip(' ').strip('/') user = self.context['request'].user prefix = '{}/{}/'.format(user.username, 'uploads') if not upload_path.startswith(prefix): error_msg = "File path must start with '%s'." % prefix raise serializers.ValidationError([error_msg]) return upload_path def validate(self, data): """ Overriden to attach the upload path to the owner object. """ # remove upload_path as it is not part of the model and attach it to the owner obj upload_path = data.pop('upload_path') owner = self.context['request'].user owner.upload_path = upload_path data['owner'] = owner return data
class UserFileSerializer(serializers.HyperlinkedModelSerializer): owner = serializers.HyperlinkedRelatedField(view_name='user-detail', read_only=True) file_resource = ItemLinkField('_get_file_link') fname = serializers.FileField() path = serializers.CharField(allow_blank=True) class Meta: model = UserFile fields = ('url', 'path', 'fname', 'file_resource', 'owner') def _get_file_link(self, obj): """ Custom method to get the hyperlink to the actual file resource """ fields = self.fields.items() # get the current url url_field = [v for (k, v) in fields if k == 'url'][0] view = url_field.view_name request = self.context['request'] format = self.context['format'] url = url_field.get_url(obj, view, request, format) # return url = current url + file name return url + os.path.basename(obj.fname.name) def validate_user_path(self, user, path): """ Custom method to check that the provided path is unique for this user in the DB. """ # remove leading and trailing slashes path = path.strip('/') path = os.path.join('/', path) try: # check if path for this file already exists in the db UserFile.objects.get(owner=user.id, path=path) except ObjectDoesNotExist: return path else: raise serializers.ValidationError( {'detail': "File already exists!"})
class PACSFileSerializer(serializers.HyperlinkedModelSerializer): file_resource = ItemLinkField('get_file_link') path = serializers.CharField(write_only=True) fname = serializers.FileField(use_url=False, required=False) fsize = serializers.ReadOnlyField(source='fname.size') pacs_identifier = serializers.ReadOnlyField(source='pacs.identifier') pacs_name = serializers.CharField(write_only=True) class Meta: model = PACSFile fields = ('url', 'id', 'creation_date', 'fname', 'fsize', 'path', 'PatientID', 'PatientName', 'PatientBirthDate', 'PatientAge', 'PatientSex', 'StudyDate', 'AccessionNumber', 'Modality', 'ProtocolName', 'StudyInstanceUID', 'StudyDescription', 'SeriesInstanceUID', 'SeriesDescription', 'pacs_identifier', 'pacs_name', 'file_resource') def get_file_link(self, obj): """ Custom method to get the hyperlink to the actual file resource. """ return get_file_resource_link(self, obj) def create(self, validated_data): """ Overriden to associate a Swift storage path with the newly created pacs file. """ # remove path as it is not part of the model and then compute fname path = validated_data.pop('path') validated_data['fname'] = path return super(PACSFileSerializer, self).create(validated_data) def validate_pacs_name(self, pacs_name): """ Overriden to check whether the provided PACS name is a valid PACS identifier. """ try: PACS.objects.get(identifier=pacs_name) except PACS.DoesNotExist: # validate new PACS identifier pacs_serializer = PACSSerializer(data={'identifier': pacs_name}) try: pacs_serializer.is_valid(raise_exception=True) except serializers.ValidationError as e: raise serializers.ValidationError(e.detail['identifier']) return pacs_name def validate_path(self, path): """ Overriden to check whether the provided path is under SERVICES/PACS/ path. """ path = path.strip(' ').strip('/') if not path.startswith('SERVICES/PACS/'): raise serializers.ValidationError( ["File path must start with 'SERVICES/PACS/'."]) # verify that the file is indeed already in Swift swift_manager = SwiftManager(settings.SWIFT_CONTAINER_NAME, settings.SWIFT_CONNECTION_PARAMS) try: swift_path_exists = swift_manager.obj_exists(path) except Exception as e: logger.error('Swift storage error, detail: %s' % str(e)) raise serializers.ValidationError(["Could not find this path."]) if not swift_path_exists: raise serializers.ValidationError(["Could not find this path."]) return path def validate(self, data): """ Overriden to validate calculated API descriptors from the provided and check whether the provided path is already registered. """ # remove pacs_name as it is not part of the model pacs_name = data.pop('pacs_name') path = data.get('path') prefix = 'SERVICES/PACS/%s/' % pacs_name if not path.startswith(prefix): error_msg = "File path must start with '%s'." % prefix raise serializers.ValidationError([error_msg]) # verify that the file has not already been registered try: PACSFile.objects.get(fname=path) except PACSFile.DoesNotExist: pass else: error_msg = "File has already been registered." raise serializers.ValidationError({'path': [error_msg]}) # update validated data with a pacs object (pacs, tf) = PACS.objects.get_or_create(identifier=pacs_name) data.update({'pacs': pacs}) return data
class ServiceFileSerializer(serializers.HyperlinkedModelSerializer): file_resource = ItemLinkField('get_file_link') path = serializers.CharField(write_only=True) fname = serializers.FileField(use_url=False, required=False) service_identifier = serializers.ReadOnlyField(source='service.identifier') service_name = serializers.CharField(write_only=True) class Meta: model = ServiceFile fields = ('url', 'id', 'creation_date', 'fname', 'path', 'service_identifier', 'service_name', 'file_resource') def get_file_link(self, obj): """ Custom method to get the hyperlink to the actual file resource. """ return get_file_resource_link(self, obj) def create(self, validated_data): """ Overriden to associate a Swift storage path with the newly created pacs file. """ # remove path as it is not part of the model and compute fname path = validated_data.pop('path') service_file = super(ServiceFileSerializer, self).create(validated_data) service_file.fname.name = path service_file.save() return service_file def validate_service_name(self, service_name): """ Overriden to check whether the provided service name is a valid service identifier. """ if service_name in REGISTERED_SERVICES: error_msg = "This is the name of a registered service. Please use the " \ "service-specific API." raise serializers.ValidationError([error_msg]) try: Service.objects.get(identifier=service_name) except Service.DoesNotExist: # validate new Service identifier service_serializer = ServiceSerializer( data={'identifier': service_name}) try: service_serializer.is_valid(raise_exception=True) except serializers.ValidationError as e: raise serializers.ValidationError(e.detail['identifier']) return service_name def validate(self, data): """ Overriden to check whether the provided path is under SERVICES/<service_name>/ path and already registered. """ # remove service_name as it is not part of the model service_name = data.pop('service_name') # verify that the file path is correct path = data.get('path') path = path.strip(' ').strip('/') prefix = 'SERVICES/%s/' % service_name if not path.startswith(prefix): error_msg = "File path must start with '%s'." % prefix raise serializers.ValidationError([error_msg]) # verify that the file is indeed already in Swift conn = swiftclient.Connection(user=settings.SWIFT_USERNAME, key=settings.SWIFT_KEY, authurl=settings.SWIFT_AUTH_URL) object_list = conn.get_container(settings.SWIFT_CONTAINER_NAME, prefix=path)[1] if not object_list: raise serializers.ValidationError( {'path': ["Could not find this path."]}) # verify that the file has not already been registered try: ServiceFile.objects.get(fname=path) except ServiceFile.DoesNotExist: pass else: error_msg = "File has already been registered." raise serializers.ValidationError({'path': [error_msg]}) # update validated data (service, tf) = Service.objects.get_or_create(identifier=service_name) data.update({'path': path, 'service': service}) return data