Django create .odt or .docx documents to download

2019-04-11 21:10发布

问题:

I need to generate either .odt or .docx files based on the information I have in my database. Let's say I have a model:

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

I want that users are able to generate office document that contains that information and also some other text. I took a look for this example which is using python-docx and it gives me an idea how to generate that document. But I can't figure out where this file is saved or is it even created. In my template I have a link:

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

where generate_docx() runs the code which can be found from the link I provided above.

How I can implement my system so that when my link is clicked, then document should be created or updated based on the data in database and after that downloaded to users computer? It's not mandatory to save that document to database but I'm also interested to hear how to do that as well.

回答1:

You can use the django template language inside a docx file, which is really a zip archive of xml files, and then run the appropriate xml file through the template engine. I got the idea here: http://reinout.vanrees.org/weblog/2012/07/04/document-automation.html

Easier said than done though. Eventually, I got it running in python3 like this:

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

And in the view:

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


回答2:

You can build you .docx file using Py2docx ( https://github.com/rafaels88/py2docx ). Put your code on a view, and after that you can do this:

# 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

Then, create a link on HTML to your view's url.



回答3:

If pdf is also an acceptable format, you might consider using django-wkhtmltopdf. It will allow you to create a normal page, and convert it to pdf using a binary form of webkit.