将内存 zip 文件写入 django FileField

Writing in memory zip file to django FileField

我正在尝试从 FileField 读取文件,将它们全部压缩并将该 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 是来自此数据包的 class: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 和 returns 字节的对象 (来自 InMemoryZip class):

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

我这辈子都想不出如何从该字节对象中读取并将其传递给 FileField。

要将内存中的文件分配给 ModelFileField,您可以使用 InMemoryUploadedFile 或者更简单的子类 SimpleUploadedFile.

此外,您不应使用 QuerySetupdate() 函数,因为它仅执行数据库查询,但不会调用模型的 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()