We love designing and developing websites, but what really drives us is solving problems and cultivating strong relationships with our clients
Generating PDFs with Django
By : shabda
If your web app creates report chances are you also want this report in PDF form. The Django docs describe a way to generate PDFs using ReportLab. Here is some code from there.
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
# Create the PDF object, using the response object as its "file."
p = canvas.Canvas(response)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
return response
This suffers from two problems,
- You are laying out your PDF using Python, which means if you later want to change the design of the PDF you need to change the Python code.
- Most of the time you already have the report in Html, form, writing the same PDF via ReportLab is error prone.
Both these problems can be cleanly solved using Pisa, a Html2Pdf library. We proceed as,
- Generate a Html representation of Pdf using normal Django macienry.
- Convert to Pdf using Pisa.
- Return PDF.
This solves both our problems as,
- Designers can edit the template to change the layout of Pdf.
- The code to generate the Html and Pdf views can share code.
Here is some example code.
def html_view(request, as_pdf = False):
#Get varaibles to populate the template
payload = {'data':data, ....}
if as_pdf:
return payload
return render_to_response('app/template.html', payload, RequestContext(request))
def pdf_view(request):
payload = html_view(request, as_pdf = True)
file_data = render_to_string('app/template.pdf', payload, RequestContext(request))
myfile = StringIO.StringIO()
pisa.CreatePDF(file_data, myfile)
myfile.seek(0)
response = HttpResponse(myfile, mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=coupon.pdf'
return response
Comments
Joshua: I documented some pitfalls I ran into on my blog. Except for these I am using pisa very successfully.
Arne's documentation of pitfalls.
http://www.arnebrodowski.de/blog/501-Pisa-and-Reportlab-pitfalls.html
I ran into a problem with the images. I don't really understand what you mean by generating a call back function?
Is it possible that you could give some clarity or code on that so that I understand how this relates in a django view? Thank you.
Small correction:
Remove:
response = HttpResponse(myfile, mimetype='application/pdf')
Add:
response = HttpResponse(myfile.getvalue(), mimetype='application/pdf')
- How to use pep8.py to write better Django code
- Screencast: Django Tutorial Part 1
- How and why to use pyflakes to write better Python
- Getting started with South for Django DB migrations
- A brief overview of Vagrant
- Writing jQuery plugins using Coffeescript
- Behind the Scenes: Request to Response
- Using SQLite Database with Android
- Haml for Django developers
- Coffeescript for Python programmers
- rails
- django
- linkroundup
- django opinion
- opinion
- business
- API
- appengine
- python
- satire
- startup
- Uncategorized
- marketing
- personal
- rambling
- search
- interviews
- seo-interviews
- 5startupideas
- ideas
- seo
- tips
- forms
- paypal
- utilities
- datetime
- web2.0
- Amazon
- algorithms
- presentations
- products
- pinax
- satchmo
- ecommerce
- microsoft
- yahoo
- book
- tutorial
- models
- aggreagtion
- meta
- India
- apps
- about
- CSS
- Design
- wordpress
- test slug
- vim
- urls
- reviews
- javascript
- xmpp
- emacs
- Typography
- Grid Theory
- Color Theory
- iphone
- android
- titanium
- mobile applications
- CSS3
- Browser Compatibility
- mobile
- jobs
- lamson
- django setup
- files
- upload
- jsTree
- hierarchical view
- web page
- Treeview
- coffeescript
- request
- response
- South
- django south
- django migration
- --fake
- screencasts
- February 2012
- January 2012
- December 2011
- October 2011
- September 2011
- July 2011
- June 2011
- April 2011
- February 2011
- January 2011
- December 2010
- November 2010
- October 2010
- September 2010
- June 2010
- April 2010
- March 2010
- January 2010
- December 2009
- November 2009
- October 2009
- September 2009
- August 2009
- July 2009
- June 2009
- April 2009
- March 2009
- February 2009
- November 2008
- October 2008
- June 2008
- May 2008
- April 2008
So it's generating the PDF from the HTML representation. Are there any pitfalls I should know about?