Красивая печать в PDF из Django

Т.к. эта статья — результат нескольких лет экспериментов, то букв будет много. Но — возможно — она сэкономит кому-то многие месяцы езды велосипедом по граблям, которые и описаны.
В общем случае речь идет даже не о Django, а о печати регламентированных документов из python с использованием шаблонизаторов.
Кому дальше читать лень — сразу скажу — проблема до конца не решена. Но более-менее рабочий вариант вырисовался.

1. Задача




2. Ограничения



Первый этап — выбор конечного формата. После недолгих размышлений с различных т.з. (кросс-платформенность, гарантированность результата, конвертируемость в) выбор пал на PDF.
Теперь — входные форматы и как их преобразовать.

3. Мягкие формы


ODF

Речь идет об Open Document Format — ODS, ODT и иже.
Здесь всё очень просто:

Место для данных: или же добавляем user-defined поля в документ — или же прямо в текст вставляем {{ теги_django }}. В первом случае заполнение этих полей потом из python — скорее всего возможно, но я даже не представляю как (точнее — всё представляемое выглядит крайне заморочливо). Поэтому просто расставляем теги в виде текста.
В этом случае заполнение полей — элементарно — просто скармливаем шаблон шаблонизатору Django (ковыряние внутри шаблона библиотеками питона оставим гентушникам :-). А дабы не раззиповывать/зазиповывать документы при каждом пинке — документы сохраняются в *.fodX (Flat X) — один-единственный неупакованный xml. Шаблонеру скармливается как xml же.
Получение PDF — без вариантов — с помощью LibreOffice: скармливаем демону LibreOffice (libreofficed (где-то у убунтоводов нашел)) или unoconv или ручной работы запускалку LO в режиме демона. Все эти варианты — примерно одно и то же.
Достоинства


Недостатки


Резюме

Как крайний запасной вариант — подходит. Но именно как крайний.
HTML

Здесь с редактированием шаблонов (руками) и шаблонизатором (искаропки) всё понятно. Остался один маленький, но главный вопрос — как получить PDF? Быстро, качественно, с разрывами страниц там, где надо. И вот здесь было больше всего экспериментов.
Многочисленные эксперименты с pure python html render (типа PISA и предков/наследников/форков) привели к одному важному (IMHO) выводу: чтобы получить гарантированный результат — надо использовать готовый html движок. Коих, как мы все знаем, аж 4 (из нормальных). Из них использовать в linux можно аж 2 — gecko и webkit. Вызвать gecko из python, скорее всего, возможно — но а) для этого нужен запущенный X (как в случае LibreOffice) и б) [полу]готового рецепта я не нашел.
Остался webkit:

Достоинства


Недостатки


Резюме

Основной вариант для “мягких” документов. Но все-таки нужно искать качественный pure python html render — без флешей, JS и других мультиков — но с качественной обработкой CSS.
Возможно

На будущее рассматриваются форматы TeX, LaTeX, Lyx, docbook — но пока преимуществ не видать (особенно для “почти мягких” форм — типа той же 21001).

4. Жесткие формы


Здесь всё намного печальнее. Особенно в свете того, что здесь уже визуальный редактор крайне желателен.
Кроме того — в подавляющем большинстве (если не во всех) “жестких” форм РФ используются “квадратики” — когда текст разбивается на буквы — и каждая вписывается в свой квадратик (пример).
Отбросим первые попавшиеся (типа “натянуть текст на tiff”) и сразу перейдем к финалистам.
RML

Разработка компании Reportlab (да-да, python-reportlab — это их) — обыкновенный XML, позволяющий выделывать чудеса с PDF. Т.к. всем известный python-trml2pdf уже RIP (как мне честно отписал его разработчик) — пришлось взять этот trml2pdf и немного допилить, т.к. он не поддерживает многие интересные фичи RML, а покупать (а тем более — ломать) коммерческий rml2pdf мне запрещает религия.
Достоинства


Недостатки

Резюме

Запасной вариант для точных форм (особенно простых).
PDF-формы

Здесь всё очень просто: исходник в PDF — и конечный результат в PDF.
  1. Берем исходную PDF-форму в левую руку
  2. XFDF (простенький xml), обработанный встроенным шаблонером Django — в правую
  3. сливаем их (populate) в новый PDF (“раскатанный” — flatten)
  4. и отдаем пользователю

Проблема всего лишь одна — п.3.
На сегодняшний день нативного и корректно работающего python API для работы с PDF-формами не обнаружено (хотя poppler кое-что уже умеет — но пилить там, судя по всему, еще много), поэтому единственный приемлемый вариант — iText. Через pdftk или свой велосипед — это уже по вкусу.
Достоинства


Недостатки


Резюме

Основной вариант для точных печатных форм.

5. Общее резюме


Итого на сегодня сформировалось:


PS. Как всё это работает — можно посмотреть здесь — без ODF и RML, но последние предусмотрены.
@
27.07.2012 19:26 UTC
Первоисточник