Запись в память zip файла в django FileField - PullRequest
0 голосов
/ 24 января 2019

Я пытаюсь прочитать файлы из FileField, поместить их все в zip и сохранить этот zip в другой FileField.Я пытаюсь избежать использования временного файла, но мне кажется, что мне, возможно, придется.

Вот что я получил до сих пор:

def generate_codified_batch(modeladmin, request, queryset):
    for batch in queryset:
        pieces = Pieces.objects.filter(batch=batch)
        mem_zip = InMemoryZipFile(file_name=batch.name)
        for piece in pieces:
            in_file = open(piece.file.path, 'rb')
            data = in_file.read()
            mem_zip.append(filename_in_zip=f'/{piece.folder_assigned}    /{piece.period}/{piece.codification}. \
                         {piece.file_name.rsplit(".")[-1]}'
                           , file_contents=data)
            in_file.close()
        files_codified = ContentFile(mem_zip.data)
        Batches.objects.filter(pk=batch.id).update(file_codified=files_codified)

InMemoryZipFile - это класс из этого пакета: https://bitbucket.org/ruamel/std.zipfile/src/faa2c8fc9e0072f57857078059ded42192af5435/init.py?at=default&fileviewer=file-view-default#init.py-57

Важны только две последние строки

files_codified = ContentFile(mem_zip.data)
Batches.objects.filter(pk=batch.id).update(file_codified=files_codified)

mem_zip.data является свойством InMemoryZip и возвращает объект байтов (из класса InMemoryZip):

self.in_memory_data = StringIO()
@property    
def data    
     return self.in_memory_data.getvalue()

Я не могуна всю жизнь выясни, как читать из этого байта объект и передавать его в FileField.

1 Ответ

0 голосов
/ 24 января 2019

Чтобы назначить файл в памяти для FileField из Model, вы можете использовать InMemoryUploadedFile или, что еще проще, его подкласс SimpleUploadedFile.

Также не следует использовать функцию QuerySet update(), потому что она выполняет только запрос к базе данных, но не вызывает метод save() модели, который сохраняет файл на диск:

Итак, в вашем коде сделайте это:

files_codified = SimpleUploadedFile.from_dict({
    'content': mem_zip.data, 
    'filename': batch.name + ".zip", 
    'content-type': 'application/zip'})
batch.files_codified = files_codified
batch.save()
...