1 ===========================
2 Outputting PDFs with Django
3 ===========================
5 This document explains how to output PDF files dynamically using Django views.
6 This is made possible by the excellent, open-source ReportLab_ Python PDF
9 The advantage of generating PDF files dynamically is that you can create
10 customized PDFs for different purposes -- say, for different users or different
13 For example, Django was used at kusports.com_ to generate customized,
14 printer-friendly NCAA tournament brackets, as PDF files, for people
15 participating in a March Madness contest.
17 .. _ReportLab: http://www.reportlab.org/rl_toolkit.html
18 .. _kusports.com: http://www.kusports.com/
23 Download and install the ReportLab library from http://www.reportlab.org/downloads.html.
24 The `user guide`_ (not coincidentally, a PDF file) explains how to install it.
26 Test your installation by importing it in the Python interactive interpreter::
30 If that command doesn't raise any errors, the installation worked.
32 .. _user guide: http://www.reportlab.com/docs/userguide.pdf
37 The key to generating PDFs dynamically with Django is that the ReportLab API
38 acts on file-like objects, and Django's ``HttpResponse`` objects are file-like
43 For more information on ``HttpResponse`` objects, see
44 `Request and response objects`_.
46 .. _Request and response objects: ../request_response/
48 Here's a "Hello World" example::
50 from reportlab.pdfgen import canvas
51 from django.http import HttpResponse
53 def some_view(request):
54 # Create the HttpResponse object with the appropriate PDF headers.
55 response = HttpResponse(mimetype='application/pdf')
56 response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
58 # Create the PDF object, using the response object as its "file."
59 p = canvas.Canvas(response)
61 # Draw things on the PDF. Here's where the PDF generation happens.
62 # See the ReportLab documentation for the full list of functionality.
63 p.drawString(100, 100, "Hello world.")
65 # Close the PDF object cleanly, and we're done.
70 The code and comments should be self-explanatory, but a few things deserve a
73 * The response gets a special mimetype, ``application/pdf``. This tells
74 browsers that the document is a PDF file, rather than an HTML file. If
75 you leave this off, browsers will probably interpret the output as HTML,
76 which would result in ugly, scary gobbledygook in the browser window.
78 * The response gets an additional ``Content-Disposition`` header, which
79 contains the name of the PDF file. This filename is arbitrary: Call it
80 whatever you want. It'll be used by browsers in the "Save as..."
83 * The ``Content-Disposition`` header starts with ``'attachment; '`` in this
84 example. This forces Web browsers to pop-up a dialog box
85 prompting/confirming how to handle the document even if a default is set
86 on the machine. If you leave off ``'attachment;'``, browsers will handle
87 the PDF using whatever program/plugin they've been configured to use for
88 PDFs. Here's what that code would look like::
90 response['Content-Disposition'] = 'filename=somefilename.pdf'
92 * Hooking into the ReportLab API is easy: Just pass ``response`` as the
93 first argument to ``canvas.Canvas``. The ``Canvas`` class expects a
94 file-like object, and ``HttpResponse`` objects fit the bill.
96 * Note that all subsequent PDF-generation methods are called on the PDF
97 object (in this case, ``p``) -- not on ``response``.
99 * Finally, it's important to call ``showPage()`` and ``save()`` on the PDF
105 If you're creating a complex PDF document with ReportLab, consider using the
106 cStringIO_ library as a temporary holding place for your PDF file. The
107 cStringIO library provides a file-like object interface that is particularly
108 efficient. Here's the above "Hello World" example rewritten to use
111 from cStringIO import StringIO
112 from reportlab.pdfgen import canvas
113 from django.http import HttpResponse
115 def some_view(request):
116 # Create the HttpResponse object with the appropriate PDF headers.
117 response = HttpResponse(mimetype='application/pdf')
118 response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
122 # Create the PDF object, using the StringIO object as its "file."
123 p = canvas.Canvas(buffer)
125 # Draw things on the PDF. Here's where the PDF generation happens.
126 # See the ReportLab documentation for the full list of functionality.
127 p.drawString(100, 100, "Hello world.")
129 # Close the PDF object cleanly.
133 # Get the value of the StringIO buffer and write it to the response.
134 pdf = buffer.getvalue()
139 .. _cStringIO: http://www.python.org/doc/current/lib/module-cStringIO.html
144 * PDFlib_ is another PDF-generation library that has Python bindings. To
145 use it with Django, just use the same concepts explained in this article.
146 * HTMLdoc_ is a command-line script that can convert HTML to PDF. It
147 doesn't have a Python interface, but you can escape out to the shell
148 using ``system`` or ``popen`` and retrieve the output in Python.
149 * `forge_fdf in Python`_ is a library that fills in PDF forms.
151 .. _PDFlib: http://www.pdflib.org/
152 .. _HTMLdoc: http://www.htmldoc.org/
153 .. _forge_fdf in Python: http://www.accesspdf.com/article.php/20050421092951834