def copy_files_to_instance(
source_files: models.QuerySet,
target: models.Model,
) -> list[File]:
if target.pk is None:
message = 'Cannot copy files to an unsaved model instance.'
raise ValueError(message)
if not source_files.exists():
return []
source_count = source_files.count()
if source_count > COPY_BATCH_SIZE_MAX:
message = (
f'Cannot copy more than {COPY_BATCH_SIZE_MAX} '
f'files at once ({source_count} requested).'
)
raise ValueError(message)
target_content_type = ContentType.objects.get_for_model(target)
path_builder = FilePathBuilder(
base_folder=settings.BASE_FOLDER_NAME,
app_name=target._meta.app_label,
)
copies = []
for source_file in source_files:
target_file = File(
content_type=target_content_type,
object_id=target.pk,
name=source_file.name,
size=source_file.size,
type=source_file.type,
related_field=source_file.related_field,
)
path = path_builder.build(
source_file.name or 'unnamed',
source_file.type or 'bin',
source_file.related_field,
)
source_file.file.open('rb')
try:
target_file.file.save(path, source_file.file, save=False)
finally:
source_file.file.close()
copies.append(target_file)
return File.objects.bulk_create(copies)