Plain Text | 160 lines | 119 code | 41 blank | 0 comment | 0 complexity | f033be026a4ca18d17348b6dfeba8d92 MD5 | raw file
1=========================== 2Outputting PDFs with Django 3=========================== 4 5This document explains how to output PDF files dynamically using Django views. 6This is made possible by the excellent, open-source ReportLab_ Python PDF 7library. 8 9The advantage of generating PDF files dynamically is that you can create 10customized PDFs for different purposes -- say, for different users or different 11pieces of content. 12 13For example, Django was used at kusports.com_ to generate customized, 14printer-friendly NCAA tournament brackets, as PDF files, for people 15participating in a March Madness contest. 16 17.. _ReportLab: http://www.reportlab.org/oss/rl-toolkit/ 18.. _kusports.com: http://www.kusports.com/ 19 20Install ReportLab 21================= 22 23Download and install the ReportLab library from http://www.reportlab.org/oss/rl-toolkit/download/. 24The `user guide`_ (not coincidentally, a PDF file) explains how to install it. 25 26Test your installation by importing it in the Python interactive interpreter:: 27 28 >>> import reportlab 29 30If that command doesn't raise any errors, the installation worked. 31 32.. _user guide: http://www.reportlab.com/docs/reportlab-userguide.pdf 33 34Write your view 35=============== 36 37The key to generating PDFs dynamically with Django is that the ReportLab API 38acts on file-like objects, and Django's :class:`~django.http.HttpResponse` 39objects are file-like objects. 40 41Here's a "Hello World" example:: 42 43 from reportlab.pdfgen import canvas 44 from django.http import HttpResponse 45 46 def some_view(request): 47 # Create the HttpResponse object with the appropriate PDF headers. 48 response = HttpResponse(mimetype='application/pdf') 49 response['Content-Disposition'] = 'attachment; filename=somefilename.pdf' 50 51 # Create the PDF object, using the response object as its "file." 52 p = canvas.Canvas(response) 53 54 # Draw things on the PDF. Here's where the PDF generation happens. 55 # See the ReportLab documentation for the full list of functionality. 56 p.drawString(100, 100, "Hello world.") 57 58 # Close the PDF object cleanly, and we're done. 59 p.showPage() 60 p.save() 61 return response 62 63The code and comments should be self-explanatory, but a few things deserve a 64mention: 65 66 * The response gets a special MIME type, ``application/pdf``. This tells 67 browsers that the document is a PDF file, rather than an HTML file. If 68 you leave this off, browsers will probably interpret the output as HTML, 69 which would result in ugly, scary gobbledygook in the browser window. 70 71 * The response gets an additional ``Content-Disposition`` header, which 72 contains the name of the PDF file. This filename is arbitrary: Call it 73 whatever you want. It'll be used by browsers in the "Save as..." 74 dialogue, etc. 75 76 * The ``Content-Disposition`` header starts with ``'attachment; '`` in this 77 example. This forces Web browsers to pop-up a dialog box 78 prompting/confirming how to handle the document even if a default is set 79 on the machine. If you leave off ``'attachment;'``, browsers will handle 80 the PDF using whatever program/plugin they've been configured to use for 81 PDFs. Here's what that code would look like:: 82 83 response['Content-Disposition'] = 'filename=somefilename.pdf' 84 85 * Hooking into the ReportLab API is easy: Just pass ``response`` as the 86 first argument to ``canvas.Canvas``. The ``Canvas`` class expects a 87 file-like object, and :class:`~django.http.HttpResponse` objects fit the 88 bill. 89 90 * Note that all subsequent PDF-generation methods are called on the PDF 91 object (in this case, ``p``) -- not on ``response``. 92 93 * Finally, it's important to call ``showPage()`` and ``save()`` on the PDF 94 file. 95 96Complex PDFs 97============ 98 99If you're creating a complex PDF document with ReportLab, consider using the 100cStringIO_ library as a temporary holding place for your PDF file. The cStringIO 101library provides a file-like object interface that is particularly efficient. 102Here's the above "Hello World" example rewritten to use ``cStringIO``:: 103 104 # Fall back to StringIO in environments where cStringIO is not available 105 try: 106 from cStringIO import StringIO 107 except ImportError: 108 from StringIO import StringIO 109 from reportlab.pdfgen import canvas 110 from django.http import HttpResponse 111 112 def some_view(request): 113 # Create the HttpResponse object with the appropriate PDF headers. 114 response = HttpResponse(mimetype='application/pdf') 115 response['Content-Disposition'] = 'attachment; filename=somefilename.pdf' 116 117 buffer = StringIO() 118 119 # Create the PDF object, using the StringIO object as its "file." 120 p = canvas.Canvas(buffer) 121 122 # Draw things on the PDF. Here's where the PDF generation happens. 123 # See the ReportLab documentation for the full list of functionality. 124 p.drawString(100, 100, "Hello world.") 125 126 # Close the PDF object cleanly. 127 p.showPage() 128 p.save() 129 130 # Get the value of the StringIO buffer and write it to the response. 131 pdf = buffer.getvalue() 132 buffer.close() 133 response.write(pdf) 134 return response 135 136.. _cStringIO: http://docs.python.org/library/stringio.html#module-cStringIO 137 138Further resources 139================= 140 141 * PDFlib_ is another PDF-generation library that has Python bindings. To 142 use it with Django, just use the same concepts explained in this article. 143 * `Pisa XHTML2PDF`_ is yet another PDF-generation library. Pisa ships with 144 an example of how to integrate Pisa with Django. 145 * HTMLdoc_ is a command-line script that can convert HTML to PDF. It 146 doesn't have a Python interface, but you can escape out to the shell 147 using ``system`` or ``popen`` and retrieve the output in Python. 148 149.. _PDFlib: http://www.pdflib.org/ 150.. _`Pisa XHTML2PDF`: http://www.xhtml2pdf.com/ 151.. _HTMLdoc: http://www.htmldoc.org/ 152 153Other formats 154============= 155 156Notice that there isn't a lot in these examples that's PDF-specific -- just the 157bits using ``reportlab``. You can use a similar technique to generate any 158arbitrary format that you can find a Python library for. Also see 159:doc:`/howto/outputting-csv` for another example and some techniques you can use 160when generated text-based formats.