1. =======================
    
  2. How to create PDF files
    
  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: https://www.reportlab.com/opensource/
    
  18. .. _kusports.com: http://www2.kusports.com/
    
  19. 
    
  20. Install ReportLab
    
  21. =================
    
  22. 
    
  23. The ReportLab library is `available on PyPI`_. A `user guide`_ (not
    
  24. coincidentally, a PDF file) is also available for download.
    
  25. You can install ReportLab with ``pip``:
    
  26. 
    
  27. .. console::
    
  28. 
    
  29.     $ python -m pip install reportlab
    
  30. 
    
  31. Test your installation by importing it in the Python interactive interpreter::
    
  32. 
    
  33.     >>> import reportlab
    
  34. 
    
  35. If that command doesn't raise any errors, the installation worked.
    
  36. 
    
  37. .. _available on PyPI: https://pypi.org/project/reportlab/
    
  38. .. _user guide: https://www.reportlab.com/docs/reportlab-userguide.pdf
    
  39. 
    
  40. Write your view
    
  41. ===============
    
  42. 
    
  43. The key to generating PDFs dynamically with Django is that the ReportLab API
    
  44. acts on file-like objects, and Django's :class:`~django.http.FileResponse`
    
  45. objects accept file-like objects.
    
  46. 
    
  47. Here's a "Hello World" example::
    
  48. 
    
  49.     import io
    
  50.     from django.http import FileResponse
    
  51.     from reportlab.pdfgen import canvas
    
  52. 
    
  53.     def some_view(request):
    
  54.         # Create a file-like buffer to receive PDF data.
    
  55.         buffer = io.BytesIO()
    
  56. 
    
  57.         # Create the PDF object, using the buffer as its "file."
    
  58.         p = canvas.Canvas(buffer)
    
  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. 
    
  68.         # FileResponse sets the Content-Disposition header so that browsers
    
  69.         # present the option to save the file.
    
  70.         buffer.seek(0)
    
  71.         return FileResponse(buffer, as_attachment=True, filename='hello.pdf')
    
  72. 
    
  73. The code and comments should be self-explanatory, but a few things deserve a
    
  74. mention:
    
  75. 
    
  76. * The response will automatically set the MIME type :mimetype:`application/pdf`
    
  77.   based on the filename extension. This tells browsers that the document is a
    
  78.   PDF file, rather than an HTML file or a generic
    
  79.   :mimetype:`application/octet-stream` binary content.
    
  80. 
    
  81. * When ``as_attachment=True`` is passed to ``FileResponse``, it sets the
    
  82.   appropriate ``Content-Disposition`` header and that tells web browsers to
    
  83.   pop-up a dialog box prompting/confirming how to handle the document even if a
    
  84.   default is set on the machine. If the ``as_attachment`` parameter is omitted,
    
  85.   browsers will handle the PDF using whatever program/plugin they've been
    
  86.   configured to use for PDFs.
    
  87. 
    
  88. * You can provide an arbitrary ``filename`` parameter. It'll be used by browsers
    
  89.   in the "Save as..." dialog.
    
  90. 
    
  91. * You can hook into the ReportLab API: The same buffer passed as the first
    
  92.   argument to ``canvas.Canvas`` can be fed to the
    
  93.   :class:`~django.http.FileResponse` class.
    
  94. 
    
  95. * Note that all subsequent PDF-generation methods are called on the PDF
    
  96.   object (in this case, ``p``) -- not on ``buffer``.
    
  97. 
    
  98. * Finally, it's important to call ``showPage()`` and ``save()`` on the PDF
    
  99.   file.
    
  100. 
    
  101. .. note::
    
  102. 
    
  103.     ReportLab is not thread-safe. Some of our users have reported odd issues
    
  104.     with building PDF-generating Django views that are accessed by many people
    
  105.     at the same time.
    
  106. 
    
  107. Other formats
    
  108. =============
    
  109. 
    
  110. Notice that there isn't a lot in these examples that's PDF-specific -- just the
    
  111. bits using ``reportlab``. You can use a similar technique to generate any
    
  112. arbitrary format that you can find a Python library for. Also see
    
  113. :doc:`/howto/outputting-csv` for another example and some techniques you can use
    
  114. when generated text-based formats.
    
  115. 
    
  116. .. seealso::
    
  117. 
    
  118.     Django Packages provides a `comparison of packages
    
  119.     <https://djangopackages.org/grids/g/pdf/>`_ that help generate PDF files
    
  120.     from Django.