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.
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
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.
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.