Generating word docs with Flask?

6.8k views Asked by At

I'm trying to spin up a single page flask application that allows users to download a word document. I've already figured out how to make/save the document using python-docx, but now I need to make the document available in the response. Any ideas?

Here's what I have so far:

from flask import Flask, render_template
from docx import Document
from cStringIO import StringIO

@app.route('/')
def index():
    document = Document()
    document.add_heading("Sample Press Release", 0)
    f = StringIO()
    document.save(f)
    length = f.tell()
    f.seek(0)
    return render_template('index.html')
4

There are 4 answers

2
Doobeh On BEST ANSWER

instead of render_template('index.html') you can just:

from flask import Flask, render_template, send_file
from docx import Document
from cStringIO import StringIO

@app.route('/')
def index():
    document = Document()
    document.add_heading("Sample Press Release", 0)
    f = StringIO()
    document.save(f)
    length = f.tell()
    f.seek(0)
    return send_file(f, as_attachment=True, attachment_filename='report.doc')
0
vikramls On

You could use the send_from_directory as in this answer.

If you are sending text, you could also use the make_response helper as in this answer.

0
Abd-Elaziz Sharaf On

For those who pass after me...

referring to these two links:

io.StringIO now replaces cStringIO.StringIO

also it will raise an error as document.save(f) should receive a pass or binary file

code should be like this:

from flask import Flask, render_template, send_file
from docx import Document
from io import BytesIO

@app.route('/')
def index():
    document = Document()
    f = BytesIO()
    # do staff with document
    document.save(f)
    f.seek(0)

    return send_file(
        f,
        as_attachment=True,
        # Use attachment_name for Flask version < 2.2.0
        download_name='report.docx'
    )

0
Patrick Mutuku On

Use

return Response(generate(), mimetype='text/docx')

Generate() should be replaced with f in your case For more information look at streaming in flask http://flask.pocoo.org/docs/1.0/patterns/streaming/