Generating word docs with Flask?
Question:
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')
Answers:
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')
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/
For those who pass after me…
referring to these two links:
- python 3.x ImportError: No module named 'cStringIO' [StackOverFlow Question]
- TypeError: string argument expected, got ‘bytes’ [GitHub issue]
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,
attachment_filename='report.docx'
)
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')
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')
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/
For those who pass after me…
referring to these two links:
- python 3.x ImportError: No module named 'cStringIO' [StackOverFlow Question]
- TypeError: string argument expected, got ‘bytes’ [GitHub issue]
io.StringIO
now replacescStringIO.StringIO
also it will raise an error
asdocument.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,
attachment_filename='report.docx'
)