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/