<commit_before>===========================
Outputting PDFs with Django
===========================

This document explains how to output PDF files dynamically using Django views.
This is made possible by the excellent, open-source ReportLab_ Python PDF
library.

The advantage of generating PDF files dynamically is that you can create
customized PDFs for different purposes -- say, for different users or different
pieces of content.

For example, Django was used at kusports.com_ to generate customized,
printer-friendly NCAA tournament brackets, as PDF files, for people
participating in a March Madness contest.

.. _ReportLab: http://www.reportlab.org/oss/rl-toolkit/
.. _kusports.com: http://www.kusports.com/

Install ReportLab
=================

Download and install the ReportLab library from http://www.reportlab.org/oss/rl-toolkit/download/.
The `user guide`_ (not coincidentally, a PDF file) explains how to install it.

Test your installation by importing it in the Python interactive interpreter::

    >>> import reportlab

If that command doesn't raise any errors, the installation worked.

.. _user guide: http://www.reportlab.com/docs/reportlab-userguide.pdf

Write your view
===============

The key to generating PDFs dynamically with Django is that the ReportLab API
acts on file-like objects, and Django's :class:`~django.http.HttpResponse`
objects are file-like objects.

Here's a "Hello World" example::

    from reportlab.pdfgen import canvas
    from django.http import HttpResponse

    def some_view(request):
        # Create the HttpResponse object with the appropriate PDF headers.
        response = HttpResponse(mimetype='application/pdf')
        response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'

        # Create the PDF object, using the response object as its "file."
        p = canvas.Canvas(response)

        # Draw things on the PDF. Here's where the PDF generation happens.
        # See the ReportLab documentation for the full list of functionality.
        p.drawString(100, 100, "Hello world.")

        # Close the PDF object cleanly, and we're done.
        p.showPage()
        p.save()
        return response

The code and comments should be self-explanatory, but a few things deserve a
mention:

    * The response gets a special MIME type, ``application/pdf``. This tells
      browsers that the document is a PDF file, rather than an HTML file. If
      you leave this off, browsers will probably interpret the output as HTML,
      which would result in ugly, scary gobbledygook in the browser window.

    * The response gets an additional ``Content-Disposition`` header, which
      contains the name of the PDF file. This filename is arbitrary: Call it
      whatever you want. It'll be used by browsers in the "Save as..."
      dialogue, etc.

    * The ``Content-Disposition`` header starts with ``'attachment; '`` in this
      example. This forces Web browsers to pop-up a dialog box
      prompting/confirming how to handle the document even if a default is set
      on the machine. If you leave off ``'attachment;'``, browsers will handle
      the PDF using whatever program/plugin they've been configured to use for
      PDFs. Here's what that code would look like::

          response['Content-Disposition'] = 'filename=somefilename.pdf'

    * Hooking into the ReportLab API is easy: Just pass ``response`` as the
      first argument to ``canvas.Canvas``. The ``Canvas`` class expects a
      file-like object, and :class:`~django.http.HttpResponse` objects fit the
      bill.

    * Note that all subsequent PDF-generation methods are called on the PDF
      object (in this case, ``p``) -- not on ``response``.

    * Finally, it's important to call ``showPage()`` and ``save()`` on the PDF
      file.

Complex PDFs
============

If you're creating a complex PDF document with ReportLab, consider using the
cStringIO_ library as a temporary holding place for your PDF file. The cStringIO
library provides a file-like object interface that is particularly efficient.
Here's the above "Hello World" example rewritten to use ``cStringIO``::

    from cStringIO import StringIO
    from reportlab.pdfgen import canvas
    from django.http import HttpResponse

    def some_view(request):
        # Create the HttpResponse object with the appropriate PDF headers.
        response = HttpResponse(mimetype='application/pdf')
        response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'

        buffer = StringIO()

        # Create the PDF object, using the StringIO object as its "file."
        p = canvas.Canvas(buffer)
<commit_msg>Fixed #12369 -- Improved example to account for environments where cStringIO is not available. Thanks to rubic for the report and niall for the patch.<commit_after>===========================
Outputting PDFs with Django
===========================

This document explains how to output PDF files dynamically using Django views.
This is made possible by the excellent, open-source ReportLab_ Python PDF
library.

The advantage of generating PDF files dynamically is that you can create
customized PDFs for different purposes -- say, for different users or different
pieces of content.

For example, Django was used at kusports.com_ to generate customized,
printer-friendly NCAA tournament brackets, as PDF files, for people
participating in a March Madness contest.

.. _ReportLab: http://www.reportlab.org/oss/rl-toolkit/
.. _kusports.com: http://www.kusports.com/

Install ReportLab
=================

Download and install the ReportLab library from http://www.reportlab.org/oss/rl-toolkit/download/.
The `user guide`_ (not coincidentally, a PDF file) explains how to install it.

Test your installation by importing it in the Python interactive interpreter::

    >>> import reportlab

If that command doesn't raise any errors, the installation worked.

.. _user guide: http://www.reportlab.com/docs/reportlab-userguide.pdf

Write your view
===============

The key to generating PDFs dynamically with Django is that the ReportLab API
acts on file-like objects, and Django's :class:`~django.http.HttpResponse`
objects are file-like objects.

Here's a "Hello World" example::

    from reportlab.pdfgen import canvas
    from django.http import HttpResponse

    def some_view(request):
        # Create the HttpResponse object with the appropriate PDF headers.
        response = HttpResponse(mimetype='application/pdf')
        response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'

        # Create the PDF object, using the response object as its "file."
        p = canvas.Canvas(response)

        # Draw things on the PDF. Here's where the PDF generation happens.
        # See the ReportLab documentation for the full list of functionality.
        p.drawString(100, 100, "Hello world.")

        # Close the PDF object cleanly, and we're done.
        p.showPage()
        p.save()
        return response

The code and comments should be self-explanatory, but a few things deserve a
mention:

    * The response gets a special MIME type, ``application/pdf``. This tells
      browsers that the document is a PDF file, rather than an HTML file. If
      you leave this off, browsers will probably interpret the output as HTML,
      which would result in ugly, scary gobbledygook in the browser window.

    * The response gets an additional ``Content-Disposition`` header, which
      contains the name of the PDF file. This filename is arbitrary: Call it
      whatever you want. It'll be used by browsers in the "Save as..."
      dialogue, etc.

    * The ``Content-Disposition`` header starts with ``'attachment; '`` in this
      example. This forces Web browsers to pop-up a dialog box
      prompting/confirming how to handle the document even if a default is set
      on the machine. If you leave off ``'attachment;'``, browsers will handle
      the PDF using whatever program/plugin they've been configured to use for
      PDFs. Here's what that code would look like::

          response['Content-Disposition'] = 'filename=somefilename.pdf'

    * Hooking into the ReportLab API is easy: Just pass ``response`` as the
      first argument to ``canvas.Canvas``. The ``Canvas`` class expects a
      file-like object, and :class:`~django.http.HttpResponse` objects fit the
      bill.

    * Note that all subsequent PDF-generation methods are called on the PDF
      object (in this case, ``p``) -- not on ``response``.

    * Finally, it's important to call ``showPage()`` and ``save()`` on the PDF
      file.

Complex PDFs
============

If you're creating a complex PDF document with ReportLab, consider using the
cStringIO_ library as a temporary holding place for your PDF file. The cStringIO
library provides a file-like object interface that is particularly efficient.
Here's the above "Hello World" example rewritten to use ``cStringIO``::

    # Fall back to StringIO in environments where cStringIO is not available
    try:
        from cStringIO import StringIO
    except ImportError:
        from StringIO import StringIO
    from reportlab.pdfgen import canvas
    from django.http import HttpResponse

    def some_view(request):
        # Create the HttpResponse object with the appropriate PDF headers.
        response = HttpResponse(mimetype='application/pdf')
        response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'

        buffer = StringIO()

        # Create the PDF object, using the StringIO object as its "file."
        p = canvas.Canvas(buffer)

{'fraction_non_alphanumeric': 0.09146786123554537, 'fraction_numerical': 0.001771017814355662, 'mean_word_length': 3.50281425891182, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 8, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7633067', 'n_tokens_mistral': 2497, 'n_tokens_neox': 2360, 'n_words': 1135}