@kotyのブログ

PythonとかAWSとか勉強会のこととかを、田舎者SEがつづります。記事のライセンスは"CC BY"でお願いします。

jinja2+WeasyPrintでお手軽印刷

過去にこんな記事を書いております。 koty.hatenablog.com この記事から4年近く過ぎた今でも印刷の需要はあります。ありますよね?

上記の記事はWPFWindowsアプリ)ですがDjangoでPDFを出す機会があったのでメモ的に残します。

おおまかな方針としては、Jinja2でHTMLを生成→WeasyPrintでPDFに変換 という流れです。

自端末のPythonのバージョンは3.6です。

requirements.txtはこちら。

WeasyPrint==0.40
Jinja2==2.9.6
Django==1.11.5

この記事としては必須ではないのですが、templateを描画するbackendがJinja2になるようsettings.pyを変更します。

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.jinja2.Jinja2',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
        },
    },
]

Jinja2に入力するhtmlのテンプレートはこちら。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>{{ title }}</title>
  <style>
    /* http://qiita.com/cognitom/items/d39d5f19054c8c8fd592 */
    @page {
      size: A4;
    }
  </style>
</head>
<body>
<h1>{{ title }}</h1>
<div>
  <ul>
    {% for skil in skills %}
      <li>{{ skil }}</li>
    {% endfor %}
  </ul>
</div>
</body>
</html>

viewはこちら。

from django.conf import settings
from django.http import HttpResponse
from jinja2 import Environment, FileSystemLoader
from weasyprint import HTML


def pdf_sample(request):
    # templateの読み込み
    template_dir = settings.TEMPLATES[0]['DIRS'][0]
    env = Environment(loader=FileSystemLoader(template_dir, encoding='utf8'))
    tpl = env.get_template('pdf_sample.html')
    # テンプレートにデータをbind
    html_str = tpl.render({
        'title':'私のスキル',
        'skills': ('python', 'django', 'C#', 'WPF', '立ち泳ぎ'),
    })
    # html文字列をPDFに変換
    pdf_file = HTML(string=html_str).write_pdf()
    return HttpResponse(pdf_file, content_type='application/pdf')

あら簡単ですね!実際にはcssでいろんな調整が必要だろうと思います。この辺を参考に。 qiita.com

PythonでPDF印刷について調べるとReportLABとかがヒットします。これだとAPIがプリミティブ過ぎて使いづらいように思います。線を一本一本引いていくなんて辛すぎます。何らかの雛形を用意してそこにデータを突っ込む、ということをしたいわけです。それにはjinja2が最適です。

1ページだけの単票(死語か?)であればこの仕掛けで十分なように思います。 一方、改ページつきで各ページに共通なヘッダを出すといった帳票の場合は何か他の、例えばWPFとかを使う必要があるかもしれません。HTMLでもできるんかな??

本件のサンプルプロジェクトは以下です。 github.com

参考サイト:

PythonユーザのためのJupyter[実践]入門

PythonユーザのためのJupyter[実践]入門