Spec-Zone.ru › Django 1.9

Вывод PDF-файлов с Django

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

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

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

Установка ReportLab

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

pip

Проверьте установку, импортировав её в интерактивный интерпретатор Python:

>>> import reportlab

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

Написание представления

Ключевым моментом в динамическом создании PDF-файлов с Django является то, что API ReportLab работает с объектами-файлами, а объекты HttpResponse Django являются объектами-файлами.

Вот пример «Hello World»:

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

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

  • Ответ получает специальный MIME-тип application/pdf. Это сообщает браузерам, что документ является PDF-файлом, а не HTML-файлом. Если этого не сделать, браузеры, вероятно, интерпретируют вывод как HTML, что приведёт к неприглядным, страшным кодировкам в окне браузера.
  • Ответ получает дополнительный Content-Disposition заголовок, содержащий имя PDF-файла. Это имя произвольное: назовите его как угодно. Оно будет использоваться браузерами в диалоговом окне «Сохранить как...» и т. д.
  • Заголовок Content-Disposition начинается с 'attachment; ' в этом примере. Это заставляет веб-браузеры отображать диалоговое окно, запрашивающее/подтверждающее, как обработать документ, даже если на компьютере установлен по умолчанию. Если вы опустите 'attachment;', браузеры будут обрабатывать PDF с помощью программы/плагина, который был настроен для работы с PDF. Вот как будет выглядеть этот код:

    response['Content-Disposition'] = 'filename="somefilename.pdf"'
    
  • Подключение к API ReportLab простое: просто передайте response в качестве первого аргумента к canvas.Canvas. Класс Canvas ожидает объект-файл, а объекты HttpResponse подходят.
  • Обратите внимание, что все последующие методы генерации PDF вызываются для объекта PDF (в данном случае p) — а не для response.
  • Наконец, важно вызвать showPage() и save() для PDF-файла.

Примечание

ReportLab не потокобезопасен. Некоторые пользователи сообщали об интересных проблемах с представлением Django для генерации PDF, к которому обращаются многие люди одновременно.

Сложные PDF-файлы

Если вы создаёте сложный PDF-документ с помощью ReportLab, рассмотрите использование библиотеки io в качестве временного хранилища для вашего PDF-файла. Эта библиотека предоставляет интерфейс объекта-файла, который особенно эффективен. Вот пример «Hello World» выше, переписанный с использованием 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

Дополнительные ресурсы

  • PDFlib — ещё одна библиотека для генерации PDF-файлов с Python-связями. Чтобы использовать её с Django, просто воспользуйтесь теми же концепциями, что описаны в этой статье.
  • XHTML2PDF — ещё одна библиотека для генерации PDF-файлов. В комплекте с ней есть пример интеграции с Django.
  • HTMLdoc — командная строка, которая может преобразовывать HTML в PDF. У неё нет Python-интерфейса, но вы можете выйти в командную строку с помощью system или popen и получить результат в Python.

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

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

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.9/howto/outputting-pdf/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API