PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

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