Мы хотим сделать архив на лету, не засоряя файловую систему и сразу отдать на загрузку клиенту. Создадим объект BytesIO и запишем в него содержимое файлов из базы в цикле. Для этого можно использовать obj.file.read(), file это FileField в вашей модели

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def download_archive_product_card(request):
"""Функция для создания архива прикрепленных документов"""
docs_ids = request.GET.getlist('docs_ids')
if not docs_ids:
logger.warning(msg="Урл для архива документов не содержит идентификаторы документов", request=request)
return JsonResponse({'message': "Please provide ids of docs you want for archive"}, status=400)
docs_ids = [int(doc) for doc in docs_ids]
docs = YourModel.get_cached_documents(docs_ids)
archive = io.BytesIO()
with zipfile.ZipFile(archive, "a") as zipf:
for doc in docs:
zipf.writestr('{}.{}'.format(doc.name, doc.extension), doc.file.read())
response = HttpResponse(zipf, content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename=%s' % 'archive.zip'
archive.seek(0)
response.write(archive.read())
return response
#кэширование в models.py
class YourModel(models.model):
title = models.CharField(max_length = 255)
thumbnail_url = models.CharField(max_length=255, default=None, null=True, blank=True)
...
@staticmethod
def get_cached_documents(docs_ids):
cache_key = '%s-%s-%s' % (__name__, 'your key', docs_ids)
documents = cache.get(cache_key)
if not documents:
documents = list(Document.objects.filter(id__in=docs_ids))
cache.set(cache_key, documents, timeout=settings.CACHE_TTL)
return documents