Генерация PDF на Django

Здесь рассказывается как генерировать PDF с помощью представлений Django. Это возможно благодаря чудесной открытой библиотеке ReportLab.

Преимущество динамической генерации PDF заключается в том, например, что вы можете создавать разный документ для разных пользователей.

Например, Django использовали на kusports.com для генерации турнирной таблицы NCAA, которую можно распечатать как обычный PDF-файл.

Установка ReportLab

Библиотека ReportLab доступна на PyPI. Документация не случайно это PDF файл) также доступна для загрузки. Вы можете установить ReportLab с помощью pip:

$ python -m pip install reportlab
...\> py -m pip install reportlab

Проверьте правильность установки с помощью импорта в интерактивном интерпретаторе:

>>> import reportlab

Если не вылезло никакой ошибки, значит установка прошла успешно.

Пишем собственное представление.

The key to generating PDFs dynamically with Django is that the ReportLab API acts on file-like objects, and Django’s FileResponse objects accept file-like objects.

Пример «Hello World»:

import io
from django.http import FileResponse
from reportlab.pdfgen import canvas

def some_view(request):
    # Create a file-like buffer to receive PDF data.
    buffer = io.BytesIO()

    # Create the PDF object, using the buffer 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, and we're done.
    p.showPage()
    p.save()

    # FileResponse sets the Content-Disposition header so that browsers
    # present the option to save the file.
    buffer.seek(0)
    return FileResponse(buffer, as_attachment=True, filename='hello.pdf')

Код и комментарии должны быть очевидными, но несколько моментов заслуживают внимания:

  • The response will automatically set the MIME type application/pdf based on the filename extension. This tells browsers that the document is a PDF file, rather than an HTML file or a generic application/octet-stream binary content.
  • When as_attachment=True is passed to FileResponse, it sets the appropriate Content-Disposition header and that tells 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 the as_attachment parameter is omitted, browsers will handle the PDF using whatever program/plugin they’ve been configured to use for PDFs.
  • You can provide an arbitrary filename parameter. It’ll be used by browsers in the «Save as…» dialog.
  • You can hook into the ReportLab API: The same buffer passed as the first argument to canvas.Canvas can be fed to the FileResponse class.
  • Note that all subsequent PDF-generation methods are called on the PDF object (in this case, p) – not on buffer.
  • Наконец, важно вызвать showPage() и save().

Примечание

ReportLab не потокобезопасна. Пользователи могут мешать друг другу в процессе построения PDF.

Другие форматы

Обратите внимание, что не так много специфики PDF в генерации документов - для ReportLab это всего лишь биты. Вы можете использовать подобную технику для генерации файла любого формата для которого есть соответствующая библиотека. В Генерация CSV на Django есть ещё примеры создания текстового формата.

См.также

Django Packages предоставляет сравнение библиотек для создания PDF файлов.