DjangoでPDFを作成する – たった3行でPDFが生成できるdjango-easy-pdfの紹介

おつです。
今回はDjangoアプリ経由でPDFの生成をします。

Django × PDF生成の下調べ – django-easy-pdf

DjangoアプリでPDFを生成したいなーとなって色々調べた結果、django-easy-pdfというライブラリが一番簡単に使えそうだった。下記はそこに到るまでの経緯や、他の候補と比較してdjango-easy-pdfを選んだ理由を書いている。さっさと使い方を教えろという方は次の章まで飛ばしてください。

ひとつめの候補:ReportLab

日本語で「Django PDF」とかって調べると真っ先に出てくるのがReportLab。
●Python + Django でPDF作成
https://qiita.com/t-iguchi/items/1bb5a85e259b190e3fbf

最初はPythonでPDF生成したいならReportLabがデファクトスタンダードに見えたんだが、使い方を見ていくうちに雲行きが怪しくなってきた。詳しくは書かないが、文書デザインをPythonのコードで表現しており、正直マジかと思った。俺はCSSで書きたかったので、ReportLabはやめにした。
(補足。なぜこれが使われているのか不思議だと思うが、どうやら、Django1.0の公式テキストでReportLabを使った方法が紹介されているらしく、それでReportLabが正式なやり方のように受け取られた経緯があるっぽい。)

ふたつめの候補:WeasyPrint

●Django2.0 + WeasyPrint でお手軽にPDF出力
https://qiita.com/nkhrk/items/c01ccb21a05c51cb1b45
これはみるからに簡単。若干記述が煩わしいが、viewのなかで色々仕込めばいいんだな、というかんじ。CSSも使える。実際に試し、ちゃんと動くことも確認できた。

さらに:django-weasyprint

●django-weasyprint
https://github.com/fdemmer/django-weasyprint
正直WeasyPrintでもよかったんだが、Django向けに調整されたWeasyPrintがあったので、当初はこれの使い方を調べて紹介記事としようとした。
ただ、githubのUsageを元にコードを書いても、細々としたエラーがいくつか出る。しょうがないからライブラリの中を見て自分で書き、白紙のPDFの生成まではできたんだが、HTMLからの変換方法を調べる過程でもっと良いライブラリを発見してしまい使うのをやめた。

最終候補:django-easy-pdf

●django-easy-pdf
https://django-easy-pdf.readthedocs.io/en/v0.2.0-dev1/
英語の情報に当たっていた際にdjango-easy-pdfなるものを発見した。これ、マジでシンプルにできていて本当に良い。機能的には素のweasyprintも良いんだが、django-easy-pdfは書き方がとてもシンプルで好きなので、今回はこれを使うことにした。

django-easy-pdf — DjangoでPDFを生成する実際の方法

インストール

こうする。

$ pip install -U django-easy-pdf WeasyPrint

インストール後、俺は下記のようなエラーが出た。

OSError: dlopen() failed to load a library: cairo / cairo-2 / cairo-gobject-2 / cairo.so.2

これはweasyprintのエラーで、前提となるソフトウェアが使っているマシンにインストールされていないことから起きるらしい。
(参考:https://github.com/Kozea/CairoSVG/issues/84
weasyprintの公式サイトにもweasyprintのインストール時に気をつける点が記載されているので、それに沿ってインストールすると良い。
https://weasyprint.readthedocs.io/en/stable/install.html#

QuickStart

さて実際の書き方。公式のQuickStart通りにやる。
●公式のQuickStart
https://django-easy-pdf.readthedocs.io/en/v0.2.0-dev1/#quickstart
まず、settings.pyeasy_pdfを追加。

INSTALLED_APPS = [
    #[中略]
    'easy_pdf',
]

次にtemplatesに用意されたHTMLを記述。

{% extends "easy_pdf/base.html" %}

{% block content %}
    <div id="content">
        <h1>Hi there!</h1>
    </div>
{% endblock %}

で最後に、views.pyにたった三行下記のコードを付け加える。

from easy_pdf.views import PDFTemplateView
class HelloPDFView(PDFTemplateView):
    template_name = 'pdf_test.html'

ルーティングの設定をし、HelloPDFViewのURLにアクセスすると、なんとこれだけでPDFが生成されている!!!

本当に簡単だ。

静的ファイルの設定

CSSをつけたい場合や、画像を含めたい場合は下記を参照。
https://django-easy-pdf.readthedocs.io/en/v0.2.0-dev1/usage.html
weasyprintの仕様上CSSファイルから適用することができないので、こんな感じにHTMLにstyleを適用する。

{% extends "easy_pdf/base.html" %}

{% block extra_style %}
    <style type="text/css">
        body {
            font-family: "Helvetica", "sans-serif";
            color: red;
        }
    </style>
{% endblock %}

{% block content %}
    <div id="content">
        <div class="main">
            <h1>Hi there!</h1>
            <img src="file:///STATIC_ROOT/img/hello.png" />
        </div>
    </div>
{% endblock %}

CSSの書き方に関しては素のweasyprintの書き方の方が好きだが、viewのエレガントさを考えるとこちらを使いたいなと思った。画像やfontは静的ファイルとしてDjangoPRJ内部に配置して、<img src="file:///STATIC_ROOT/img/hello.png" />みたいな感じにリンクを貼る。

また、サンプルアプリを公開してくれている人がいたので、こちらも参照してみるとわかりやすいかもしれない。
https://github.com/jaysnm/django-easyふ-pdf-demo-app

最後に

感想。今までずっとQiita記事とかを読んで勉強してきたけど、こういう風に英語のソースまで探すってのはかなりいい経験になった。日本語には翻訳されていないけれど本当は使いやすいライブラリとかっていっぱいあるんだろうな。今回こうやって紹介できてよかったし、誰かの役に立てば幸い。今後も知られてないライブラリを発掘して広めたいなって思いました。

参考にしたページ

・DjangoでPDFを生成する
https://qiita.com/t-iguchi/items/1bb5a85e259b190e3fbf
・xhtml2pdf – ReportLabを使用してHTMLをPDFに変換するためのライブラリ
https://githubja.com/xhtml2pdf/xhtml2pdf
・「Django2.0 + WeasyPrint でお手軽にPDF出力」
https://qiita.com/nkhrk/items/c01ccb21a05c51cb1b45
・WeasyPrint公式
https://weasyprint.readthedocs.io/en/latest/index.html
・django-weasyprintのgithub
https://github.com/fdemmer/django-weasyprint
・django-easy-pdfの公式
https://django-easy-pdf.readthedocs.io/en/v0.2.0-dev1/#
・サンプルAPP
https://github.com/jaysnm/django-easy-pdf-demo-app
・ログの取り方
https://qiita.com//second_seal/items/a3c6e95161e0c956beca

以上!!!