Вывод PDF-файлов с помощью Django
В этом документе объясняется, как динамически выводить PDF-файлы с помощью представлений Django. Это становится возможным благодаря отличной, открытой библиотеке Python для работы с PDF ReportLab.
Преимущество динамического создания PDF-файлов заключается в том, что вы можете создавать настраиваемые PDF-файлы для разных целей — например, для разных пользователей или разных фрагментов контента.
Например, Django использовался на сайте kusports.com для генерации настраиваемых, удобных для печати PDF-файлов с турнирными скобками NCAA для людей, участвующих в конкурсе «Мартовский безумство».
Установка ReportLab
Библиотека ReportLab доступна на PyPI. Также доступно руководство пользователя (неслучайно, в формате PDF) для скачивания. Вы можете установить ReportLab с помощью:
$ pip install reportlab
Проверьте установку, импортировав её в интерактивном интерпретаторе Python:
>>> import reportlab
Если эта команда не вызовет никаких ошибок, установка прошла успешно.
Написание представления
Ключ к динамическому созданию PDF-файлов с помощью Django заключается в том, что API ReportLab работает с объектами, подобными файлам, а объекты HttpResponse Django также являются объектами, подобными файлам.
Вот пример «Привет, мир»:
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-файла. Эта библиотека предоставляет интерфейс, подобный файлам, который особенно эффективен. Вот пример «Привет, мир» выше, переписанный с использованием 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 используйте те же принципы, что и в этой статье.
- Pisa XHTML2PDF — ещё одна библиотека для генерации PDF-файлов. Pisa поставляется с примером интеграции Pisa с 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.8/howto/outputting-pdf/