PageRenderTime 65ms CodeModel.GetById 61ms app.highlight 1ms RepoModel.GetById 1ms app.codeStats 0ms

/docs/howto/outputting-pdf.txt

https://code.google.com/p/mango-py/
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.