Python
Django
PDF
WeasyPrint

Django2.0 + WeasyPrint でお手軽にPDF出力

WeasyPrintとは

  • HTMLを簡単なコードでPDFやPNGなどの静的ファイルに変換、出力ができるPythonで書かれたOSSライブラリです。
  • 公式サイト

導入方法

  • ここを参照
    • 環境にもよるが、 libffi などの外部ライブラリが必要なので必要に応じてインストールする。参考:Macの場合

基本的な使い方

ここにも書いてありますが、

from weasyprint import HTML

で weasyprintのHTML classをimportして

HTML('https://qiita.com/').write_pdf('/tmp/qiita.pdf')

のように引数に対象ページのURLを指定したHTMLオブジェクトの write_pdf メソッドで引数に出力パスを指定するだけでPDF化されます。

生のHTMLを渡してレンダリングされたものをPDF化することも可能です。

from weasyprint import HTML

HTML(string='''
    <h1>Hello World</h1>
''')

Djangoで表示されるTemplateをPDF化してみよう

DjangoのViewにPDF出力用の関数を用意し、そこにURLルーティングしている前提です。

def pdf_export(request):

まずはDjangoのTemplateをロードする。

from django.template.loader import get_template
html_template = get_template('hoge/fuga.html')

次に、ロードしたTemplateをHTML化する

# Templateに渡すオブジェクトがある場合は、以下のようにdictで指定する。
html_str = html_template.render({
    'param1': 'hoge',
    'param2': 'fuga',
}, request)

生成したHTMLをPDF化する

pdf_file = HTML(string=html_str).write_pdf(
    # 必要に応じてCSSを指定する。Template内で直接指定しているCSSはWeasyPrint経由だと参照されないので注意。
    stylesheets=[
        CSS('/static/css/hoge.css')
    ],
)

生成したPDFをHTTPのレスポンスとして返却する

response = HttpResponse(pdf_file, content_type='application/pdf')
# ストレージに保存する際のデフォルトファイル名を指定できる
response['Content-Disposition'] = 'filename="fuga.pdf"'

return response

これだけです。
とても簡単ですね。

最終的に以下のような形になります。

def pdf_export(request):
    from django.template.loader import get_template
    html_template = get_template('hoge/fuga.html')

    html_str = html_template.render(request)  # ここでrequestを渡してあげないと、Template側で必要な変数やプリセットなどが取得できずエラーになる場合がある

    pdf_file = HTML(string=html_str).write_pdf(
        # 必要に応じてCSSを指定する。Template内で直接指定しているCSSはWeasyPrint経由だと参照されないので注意。
        stylesheets=[
            CSS('/static/css/hoge.css')
        ],
    )

    response = HttpResponse(pdf_file, content_type='application/pdf')
    # ストレージに保存する際のデフォルトファイル名を指定できる
    response['Content-Disposition'] = 'filename="fuga.pdf"'

    return response

上記の関数にブラウザからアクセスすると、指定したTemplateのPDFがダウンロードできます。