| 1 |
=========================== |
|---|
| 2 |
Outputting PDFs with Django |
|---|
| 3 |
=========================== |
|---|
| 4 |
|
|---|
| 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 |
|---|
| 7 |
library. |
|---|
| 8 |
|
|---|
| 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 |
|---|
| 11 |
pieces of content. |
|---|
| 12 |
|
|---|
| 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. |
|---|
| 16 |
|
|---|
| 17 |
.. _ReportLab: http://www.reportlab.org/rl_toolkit.html |
|---|
| 18 |
|
|---|
| 19 |
Install ReportLab |
|---|
| 20 |
================= |
|---|
| 21 |
|
|---|
| 22 |
Download and install the ReportLab library from http://www.reportlab.org/downloads.html. |
|---|
| 23 |
The `user guide`_ (not coincidentally, a PDF file) explains how to install it. |
|---|
| 24 |
|
|---|
| 25 |
Test your installation by importing it in the Python interactive interpreter:: |
|---|
| 26 |
|
|---|
| 27 |
>>> import reportlab |
|---|
| 28 |
|
|---|
| 29 |
If that command doesn't raise any errors, the installation worked. |
|---|
| 30 |
|
|---|
| 31 |
.. _user guide: http://www.reportlab.org/rsrc/userguide.pdf |
|---|
| 32 |
|
|---|
| 33 |
Write your view |
|---|
| 34 |
=============== |
|---|
| 35 |
|
|---|
| 36 |
The key to generating PDFs dynamically with Django is that the ReportLab API |
|---|
| 37 |
acts on file-like objects, and Django's ``HttpResponse`` objects are file-like |
|---|
| 38 |
objects. |
|---|
| 39 |
|
|---|
| 40 |
.. admonition:: Note |
|---|
| 41 |
|
|---|
| 42 |
For more information on ``HttpResponse`` objects, see |
|---|
| 43 |
`Request and response objects`_. |
|---|
| 44 |
|
|---|
| 45 |
.. _Request and response objects: http://www.djangoproject.com/documentation/request_response/ |
|---|
| 46 |
|
|---|
| 47 |
Here's a "Hello World" example:: |
|---|
| 48 |
|
|---|
| 49 |
from reportlab.pdfgen import canvas |
|---|
| 50 |
from django.utils.httpwrappers import HttpResponse |
|---|
| 51 |
|
|---|
| 52 |
def some_view(request): |
|---|
| 53 |
# Create the HttpResponse object with the appropriate PDF headers. |
|---|
| 54 |
response = HttpResponse(mimetype='application/pdf') |
|---|
| 55 |
response['Content-Disposition'] = 'attachment; filename=somefilename.pdf' |
|---|
| 56 |
|
|---|
| 57 |
# Create the PDF object, using the response object as its "file." |
|---|
| 58 |
p = canvas.Canvas(response) |
|---|
| 59 |
|
|---|
| 60 |
# Draw things on the PDF. Here's where the PDF generation happens. |
|---|
| 61 |
# See the ReportLab documentation for the full list of functionality. |
|---|
| 62 |
p.drawString(100, 100, "Hello world.") |
|---|
| 63 |
|
|---|
| 64 |
# Close the PDF object cleanly, and we're done. |
|---|
| 65 |
p.showPage() |
|---|
| 66 |
p.save() |
|---|
| 67 |
return response |
|---|
| 68 |
|
|---|
| 69 |
The code and comments should be self-explanatory, but a few things deserve a |
|---|
| 70 |
mention: |
|---|
| 71 |
|
|---|
| 72 |
* The response gets a special mimetype, ``application/pdf``. This tells |
|---|
| 73 |
browsers that the document is a PDF file, rather than an HTML file. If |
|---|
| 74 |
you leave this off, browsers will probably interpret the output as HTML, |
|---|
| 75 |
which would result in ugly, scary gobbledygook in the browser window. |
|---|
| 76 |
|
|---|
| 77 |
* The response gets an additional ``Content-Disposition`` header, which |
|---|
| 78 |
contains the name of the PDF file. This filename is arbitrary: Call it |
|---|
| 79 |
whatever you want. It'll be used by browsers in the "Save as..." |
|---|
| 80 |
dialogue, etc. |
|---|
| 81 |
|
|---|
| 82 |
* Hooking into the ReportLab API is easy: Just pass ``response`` as the |
|---|
| 83 |
first argument to ``canvas.Canvas``. The ``Canvas`` class expects a |
|---|
| 84 |
file-like object, and ``HttpResponse`` objects fit the bill. |
|---|
| 85 |
|
|---|
| 86 |
* Note that all subsequent PDF-generation methods are called on the PDF |
|---|
| 87 |
object (in this case, ``p``) -- not on ``response``. |
|---|
| 88 |
|
|---|
| 89 |
* Finally, it's important to call ``showPage()`` and ``save()`` on the PDF |
|---|
| 90 |
file. |
|---|