Здесь рассказывается как генерировать PDF с помощью представлений Django. Это возможно благодаря чудесной открытой библиотеке ReportLab.
Преимущество динамической генерации PDF заключается в том, например, что вы можете создавать разный документ для разных пользователей.
Например, Django использовали на kusports.com для генерации турнирной таблицы NCAA, которую можно распечатать как обычный PDF-файл.
Библиотека ReportLab доступна на PyPI. Документация не случайно это PDF файл) также доступна для загрузки. Вы можете установить ReportLab с помощью pip:
$ pip install reportlab
Проверьте правильность установки с помощью импорта в интерактивном интерпретаторе:
>>> import reportlab
Если не вылезло никакой ошибки, значит установка прошла успешно.
Ключевым фактором в динамической генерации PDF с помощью Django является то, что ReportLab API работает с файловыми объектами, также, как и HttpResponse.
Пример “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
Код и комментарии должны быть очевидными, но несколько моментов заслуживают внимания:
Ответу устанавливается специальный тип application/pdf. Этим мы говорим браузеру, что результат запроса - документ PDF, а не HTML файл. Если этого не сделать, то браузер может попытаться интерпретировать его как HTML, что приведёт к ужасным, страшным абракадабрам в окне браузера.
Ответ получает дополнительный заголовок Content-Disposition, в котором указывается имя PDF-файла. Имя файла здесь произвольное - называйте его как хотите. Оно будет использовано браузером в диалоге “Сохранить как...” и других случаях.
Заголовок Content-Disposition в этом примере не зря начинается с 'attachment; ' . Это заставляет браузер показать всплывающее окно с выбором как же обрабатывать документ, даже если задано поведение по умолчанию. Если вы не укажите 'attachment;', браузер будет обрабатывать его плагинами, которые работают с PDF. Для этого нужно указать как-то так:
response['Content-Disposition'] = 'filename="somefilename.pdf"'
Подключить ReportLab довольно просто: просто передайте response в качестве первого аргумента в canvas.Canvas. Класс Canvas ожидает любой файловый объект, а HttpResponse как раз прекрасно подходит на данную роль.
Следует отметить, что все последующие действия нужно производить с получившимся объектом (в данном случае с p), а не с response.
Наконец, важно вызвать showPage() и save().
Примечание
ReportLab не потокобезопасна. Пользователи могут мешать друг другу в процессе построения PDF.
Если вы создаёте сложные PDF документы с помощью ReportLab, рассмотрите библиотеку io как временное хранилище для результата. Эта библиотека предоставляет файловый объект, который наиболее эффективен. Пример “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, используйте те же понятия, которые описаны в этой статье.
Pisa XHTML2PDF - ещё одна библиотека для генерации PDF. Пример как использовать её вместе с Django можно найти в её документации.
HTMLdoc - скрипт для конвертации HTML в PDF. У него нет интерфейса для Python, но вы можете избежать использования командной строки, используя system или popen для перенаправления вывода своих скриптов.
Обратите внимание, что не так много специфики PDF в генерации документов - для ReportLab это всего лишь биты. Вы можете использовать подобную технику для генерации файла любого формата для которого есть соответствующая библиотека. В Генерация CSV на Django есть ещё примеры создания текстового формата.
Mar 31, 2016