Skip to content

file#

File#

Bases: SystemCreatorBaseModel, SoftDeletableModel

A file stored in external data storage.

Source code in src/apps/files/models/file.py
class File(SystemCreatorBaseModel, SoftDeletableModel):
    """A file stored in external data storage."""

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

    # timestamp fields prefixed with record_ to avoid confusion with values from storage service
    record_created = AutoCreatedField(_("created"))
    record_modified = AutoLastModifiedField(_("modified"))

    storage_identifier = models.CharField(
        max_length=200, null=True, help_text=_("Identifier of file in external storage service")
    )
    filename = models.TextField()
    directory_path = models.TextField(db_index=True)  # not directly exposed in the API
    size = models.BigIntegerField(default=0, help_text=_("File size in bytes."))

    checksum = models.TextField(
        help_text=_(
            "Checksum as a lowercase string in format 'algorithm:value'. Allowed algorithms: {}"
        ).format(ChecksumField.allowed_algorithms)
    )

    frozen = models.DateTimeField(null=True, blank=True, db_index=True)
    modified = models.DateTimeField()
    removed = models.DateTimeField(null=True, blank=True)

    # TODO: characteristics = JSONField(blank=True, null=True)
    # TODO?: characteristics_extension = JSONField(blank=True, null=True)

    storage = models.ForeignKey(FileStorage, related_name="files", on_delete=models.CASCADE)
    is_pas_compatible = models.BooleanField(default=None, null=True, blank=True)

    user = models.CharField(max_length=200, null=True, blank=True)

    @property
    def pathname(self) -> str:
        return f"{self.directory_path}{self.filename}"

    @pathname.setter
    def pathname(self, value: str):
        path, name = value.rsplit("/", 1)
        self.filename = name
        self.directory_path = f"{path}/"

    @property
    def csc_project(self) -> str:
        if self.storage:
            return self.storage.csc_project

    @property
    def storage_service(self) -> str:
        if self.storage.storage_service:
            return self.storage.storage_service

    class Meta:
        indexes = [
            models.Index(fields=("directory_path", "storage")),
            models.Index(fields=("directory_path", "filename")),
        ]
        ordering = ["directory_path", "filename"]

        constraints = [
            models.CheckConstraint(
                check=~models.Q(filename=""),
                name="%(app_label)s_%(class)s_require_filename",
            ),
            models.CheckConstraint(
                check=models.Q(directory_path__startswith="/")
                & models.Q(directory_path__endswith="/"),
                name="%(app_label)s_%(class)s_require_dir_slash",
            ),
            # pathname should be unique for storage
            models.UniqueConstraint(
                fields=["filename", "directory_path", "storage"],
                condition=models.Q(is_removed=False),
                name=",%(app_label)s_%(class)s_unique_file_path",
            ),
            # identifier should be unique for storage
            models.UniqueConstraint(
                fields=["storage_identifier", "storage"],
                condition=models.Q(is_removed=False) & models.Q(storage_identifier__isnull=False),
                name="%(app_label)s_%(class)s_unique_identifier",
            ),
        ]

    def delete(self, using=None, soft=True, *args, **kwargs):
        """Override delete method to add record_removed"""
        self.removed = timezone.now()
        return super().delete(using=using, soft=soft, *args, **kwargs)

delete(using=None, soft=True, *args, **kwargs) #

Override delete method to add record_removed

Source code in src/apps/files/models/file.py
def delete(self, using=None, soft=True, *args, **kwargs):
    """Override delete method to add record_removed"""
    self.removed = timezone.now()
    return super().delete(using=using, soft=soft, *args, **kwargs)