Josh Lewis

Generating PDF Exports in Django

Creating PDF's is a frequent requirement in many Django applications but it can be a messy process unless you want to define every graphical element from scratch.

Generating a PDF from HTML is messy. In my experience I've found two solutions, both of which are a compromise, but work:

  • Using Reportlab and the Django easy-pdf library.
  • Making use of a browsers built in ability to save to PDF using print styling.

Reportlab

The Django easy-pdf library makes use of Reportlab, an open-source PDF generation toolkit.

Easy PDF allows you to import a render_to_pdf_response method that can be used just like Django's from django.shortcuts.render function to return a view.

from easy_pdf.rendering import render_to_pdf_response

It can be passed a HTML template and a dictionary of variables to render the template with:

if 'pdf' in request.GET:
     return render_to_pdf_response(request, 'invoice.html', {'invoice':invoice,})

So far so good. The only real disadvantage is that you can't render a normal template with an included CSS file, but instead must use special style attributes. An example easy_pdf/base.html provides an example and can be extended from if you are using easy_pdf.

This alternative CSS syntax or the requirement that CSS is inlined in order to work makes it more painful to work with although the end result is good. Web fonts don't appear to work either and so local versions must be provided.

Note: when installing Reportlab I often encounter this bug, which has a straight forward workaround.

Save as PDF

A slightly cruder alternative, but one which is much easier to implement and is perfectly suitable for applications where only a few users will need to use it is using print styling.

By creating a new HTML page with a media="print" style sheet attached and adding the below script to the page:

<script type="text/javascript">
window.onload = function () { window.print(); }
</script>

We can create a page that loads the print dialog as soon as it is opened the option to save it as a PDF is easily available. The print CSS can then be used to style the ‘PDF” as any other web-page without worrying about inline styling or positioning. In Chrome you have to select a checkbox to include background colours in the printed version, so this is something that should be bared in mind.

This method allows you to use web fonts which render normally and is very quick and easy to do — I use it in my own admin system when generating invoices or quotes.