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.
The ReportLab library is available on PyPI. A user guide (not coincidentally, a PDF file) is also available for download. You can install ReportLab with pip:
$ pip install reportlab
Test your installation by importing it in the Python interactive interpreter:
>>> import reportlab
If that command doesn’t raise any errors, the installation worked.
The key to generating PDFs dynamically with Django is that the ReportLab API acts on file-like objects, and Django’s 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(content_type='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:
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…” dialog, 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"'
response as the first argument to canvas.Canvas. The Canvas class expects a file-like object, and HttpResponse objects fit the bill. p) – not on response. showPage() and save() on the PDF file. Note
ReportLab is not thread-safe. Some of our users have reported odd issues with building PDF-generating Django views that are accessed by many people at the same time.
If you’re creating a complex PDF document with ReportLab, consider using the io library as a temporary holding place for your PDF file. This library provides a file-like object interface that is particularly efficient. Here’s the above “Hello World” example rewritten to use io:
from io import BytesIO
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(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
    buffer = BytesIO()
    # Create the PDF object, using the BytesIO object as its "file."
    p = canvas.Canvas(buffer)
    # 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.
    p.showPage()
    p.save()
    # Get the value of the BytesIO buffer and write it to the response.
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response
   Notice that there isn’t a lot in these examples that’s PDF-specific – just the bits using reportlab. You can use a similar technique to generate any arbitrary format that you can find a Python library for. Also see Outputting CSV with Django for another example and some techniques you can use when generated text-based formats.
See also
Django Packages provides a comparison of packages that help generate PDF files from Django.
    © Django Software Foundation and individual contributors
Licensed under the BSD License.
    https://docs.djangoproject.com/en/1.11/howto/outputting-pdf/