简体   繁体   English

如何使用 python-docx 从模板流式传输文件

[英]How use python-docx to stream a file from template

Ok so right now I have a function in my django app that creates a word document like so:好的,现在我的 django 应用程序中有一个函数可以创建一个 word 文档,如下所示:

def form_view(request):

    if request.method == 'POST':
       #do a bunch of things
       context = { 
        'model_1' : model_1,
        }
        in_template = "Forms/mytemplate.docx"

        doc = DocxTemplate(in_template)
        doc.render(context)
        out_filename = "outfile.docx"
        http_word_response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
        http_word_response['Content-Disposition'] = 'attachment; filename=%s' % out_filename
        doc.save(http_word_response)
        return http_word_response

     else:
       return render( request, 'mysite/form.html', context)

So right now, the file is served up as the http_word_response variable and it works great所以现在,该文件作为http_word_response变量提供,并且效果很好

I want to change this so that the file is actually created and saved into S3, but I'd like to not save the file locally first and just use the stream function of the python-docx package: https://python-docx.readthedocs.io/en/latest/user/documents.html#opening-a-file-like-document我想更改此设置,以便实际创建文件并将其保存到 S3 中,但我不想先将文件保存在本地,而只需使用 python-docx 包的流函数: https://python-docx。 readthedocs.io/en/latest/user/documents.html#opening-a-file-like-document

Here's the sample it gives:这是它提供的示例:

with open('foobar.docx', 'rb') as f:
    source_stream = StringIO(f.read())
document = Document(source_stream)
source_stream.close()
...
target_stream = StringIO()
document.save(target_stream)

I'm not sure how to translate that sample into reading in my template file and outputting a file/object I can then send to S3 and do something with.我不确定如何将该样本转换为读取我的模板文件并输出一个文件/对象,然后我可以将其发送到 S3 并进行处理。

My best guess would start like this:我最好的猜测是这样开始的:

        with open(in_template, 'rb') as f:
            source_stream = StringIO(f.read())
        doc = DocxTemplate(source_stream)
        source_stream.close()

        target_stream = StringIO()
        document.save(target_stream)

But then I get confused on where my doc.render(context) part goes and how I can change the name of the target_stream to a filename I want.但是后来我对我的doc.render(context)部分的位置以及如何将target_stream的名称更改为我想要的文件名感到困惑。

Any help on getting started with that is appreciated.任何有关入门的帮助表示赞赏。

Late to the party here, I assume you already found the answer, but anyway...迟到了,我想你已经找到了答案,但无论如何......

source_stream and target_stream are StringIO objects, text streams that use an in-memory text buffer. source_streamtarget_stream是 StringIO 对象,使用内存文本缓冲区的文本流。 Think of them as in-memory files, without any info about their paths.将它们视为内存中的文件,没有关于它们的路径的任何信息。

Your guess is good, and the doc.render(context) goes in the empty line, right after creating the DocxTemplate and closing the source_stream (since you don't need it anymore).您的猜测很好,并且doc.render(context)在创建DocxTemplate并关闭source_stream之后进入空行(因为您不再需要它)。

To post the target_stream to s3, you can use the smart open library, with something like this:要将target_stream到 s3,您可以使用智能开放库,如下所示:

from smart_open import open

with open('s3://bucket/key.txt', 'wb', transport_params=transport_params) as fout:
    fout.write(target_stream)

See smart open documentation for info about the parameters.有关参数的信息,请参阅智能打开文档。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM