Skip to content

handlers

django_spire.file.handlers

BaseFileHandler dataclass

factory instance-attribute

linker instance-attribute

__post_init__

Source code in django_spire/file/handlers.py
def __post_init__(self) -> None:
    if self.factory.related_field != self.linker.related_field:
        message = 'factory.related_field and linker.related_field must match.'
        raise ValueError(message)

add

Source code in django_spire/file/handlers.py
def add(self, file: InMemoryUploadedFile, instance: models.Model) -> File:
    file_obj = self.factory.create(file)
    return self.linker.link(file_obj, instance)

remove

Source code in django_spire/file/handlers.py
def remove(self, file_id: int, instance: models.Model) -> bool:
    content_type = ContentType.objects.get_for_model(instance)

    updated = (
        File.objects
        .active()
        .filter(
            pk=file_id,
            content_type=content_type,
            object_id=instance.pk,
        )
        .related_field(self.linker.related_field)
        .update(is_active=False, is_deleted=True)
    )

    return updated > 0

remove_all

Source code in django_spire/file/handlers.py
def remove_all(self, instance: models.Model) -> int:
    return self.linker.unlink_existing(instance)

SingleFileHandler dataclass

Bases: BaseFileHandler

Source code in django_spire/file/handlers.py
@classmethod
def for_related_field(
    cls,
    related_field: str = '',
    validator: FileValidator | None = None,
    app_name: str = 'Uncategorized',
) -> SingleFileHandler:
    factory_kwargs = {'related_field': related_field, 'app_name': app_name}

    if validator is not None:
        factory_kwargs['validator'] = validator

    return cls(
        factory=FileFactory(**factory_kwargs),
        linker=FileLinker(related_field=related_field),
    )

replace

Source code in django_spire/file/handlers.py
def replace(
    self,
    data: dict | InMemoryUploadedFile | None,
    instance: models.Model,
) -> File | None:
    if data is None:
        return None

    if isinstance(data, dict):
        return self._replace_from_ajax(data, instance)

    if isinstance(data, UploadedFile):
        return self._replace_from_upload(data, instance)

    message = f'Unsupported data type: {type(data).__name__}'
    raise TypeError(message)

MultiFileHandler dataclass

Bases: BaseFileHandler

Source code in django_spire/file/handlers.py
@classmethod
def for_related_field(
    cls,
    related_field: str = '',
    validator: FileValidator | None = None,
    app_name: str = 'Uncategorized',
) -> MultiFileHandler:
    factory_kwargs = {'related_field': related_field, 'app_name': app_name}

    if validator is not None:
        factory_kwargs['validator'] = validator

    return cls(
        factory=FileFactory(**factory_kwargs),
        linker=FileLinker(related_field=related_field),
    )

add_many

Source code in django_spire/file/handlers.py
def add_many(self, files: list[InMemoryUploadedFile], instance: models.Model) -> list[File]:
    if not files:
        return []

    file_objs = self.factory.create_many(files)
    self.linker.link_many(file_objs, instance)
    return file_objs

replace

Source code in django_spire/file/handlers.py
def replace(
    self,
    data: list[dict] | list[InMemoryUploadedFile] | None,
    instance: models.Model,
) -> list[File]:
    if not data:
        return []

    if len(data) > BATCH_SIZE_MAX:
        message = f'Cannot process more than {BATCH_SIZE_MAX} files at once.'
        raise FileBatchLimitError(message)

    first = data[0]

    if isinstance(first, dict):
        if not all(isinstance(element, dict) for element in data):
            message = 'Cannot mix file uploads and existing file references in the same request.'
            raise TypeError(message)

        return self._replace_from_ajax(data, instance)

    if isinstance(first, UploadedFile):
        if not all(isinstance(element, UploadedFile) for element in data):
            message = 'Cannot mix file uploads and existing file references in the same request.'
            raise TypeError(message)

        return self._replace_from_upload(data, instance)

    message = f'Unsupported data element type: {type(first).__name__}'
    raise TypeError(message)