Django生成可下载的.odt或.docx文档

3 投票
3 回答
4644 浏览
提问于 2025-04-17 21:58

我需要根据数据库里的信息生成 .odt 或 .docx 文件。假设我有一个模型:

class Contact(models.Model):
    first_name = models.CharField()
    last_name = models.CharField()
    email = models.EmailField()

我希望用户能够生成包含这些信息和其他一些文本的办公文档。我查看了这个例子,它使用了 python-docx,给了我一些生成文档的思路。但是我搞不清楚这个文件保存在哪里,或者说它是否真的被创建了。在我的模板里有一个链接:

<a href="{{ contact.generate_docx }}">generate .docx document</a>

这里的 generate_docx() 运行了我上面提供链接中的代码。

我该如何实现我的系统,让用户点击链接时,文档能够根据数据库中的数据被创建或更新,然后下载到用户的电脑上? 不一定要把文档保存到数据库里,但我也想知道如果要这样做该怎么做。

3 个回答

0

如果pdf也是可以接受的格式,你可以考虑使用django-wkhtmltopdf。这个工具可以让你先创建一个普通的网页,然后通过一种叫做webkit的程序把它转换成pdf格式。

2

你可以使用 Py2docx 来创建 .docx 文件,具体可以在这个链接找到:https://github.com/rafaels88/py2docx。首先,把你的代码放在一个视图里,然后你可以这样做:

# Here goes the Py2docx code
# After save the .docx file, do this:

file_docx = open("path/file.docx", 'r')
response = HttpResponse(mimetype='text/html')
response['Content-Disposition'] = 'attachment; filename=file_name.docx'
response['Content-Encoding'] = 'UTF-8'
response['Content-type'] = 'text/html; charset=UTF-8'
response.write(file_docx.read())
file_docx.close()
return response

接着,在 HTML 中创建一个链接,指向你视图的 URL。

3

你可以在docx文件中使用django模板语言,其实docx文件就是一堆xml文件打包成的zip文件。然后你可以把合适的xml文件通过模板引擎来处理。我是在这里得到这个想法的:http://reinout.vanrees.org/weblog/2012/07/04/document-automation.html

不过说起来简单,做起来可不容易。最后,我在python3中这样实现了:

from zipfile import ZipFile
from io import BytesIO

from django.template import Context, Template

def render_to_docx(docx, context):
    tmp = BytesIO()
    with ZipFile(tmp, 'w') as document_zip, ZipFile(docx) as template_zip:
        template_archive = {name: template_zip.read(name) for name in template_zip.namelist()}
        template_xml = template_archive.pop('word/document.xml')
        for n, f in template_archive.items():
            document_zip.writestr(n, f)
        t = Template(template_xml)
        document_zip.writestr('word/document.xml', t.render(Context(context)))        
    return tmp

在视图中:

response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document')
response['Content-Disposition'] = 'attachment; filename=document.docx'
zipfile = render_to_docx('template.docx'), context_dictionary)
response.write(zipfile.getvalue())
return response

撰写回答