Django生成可下载的.odt或.docx文档
我需要根据数据库里的信息生成 .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