Вывод 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/