掲題の通り、Djangoで作成した画面をweasyprintを使ってPDF出力して印刷できるようにします。
まずは、weasyprintをインストールします。
しかし、いろんな物に依存関係があるようなので色々パッケージのインストールが必要です。
エラーを確認しながら進めます。なんか行き当たりばったりです。
環境
- python : 3系
- Django : version 3.0.2
- SQLite
- macOS Catalina
とりあえず、何かしらのアプリが作成されていることが前提です。
ついでにHomebrewもインストールされていることも前提です。
weasyprintインストール
Djangoのバーチャル環境にインストールするので、アプリをアクティベートしてからターミナルで以下のコマンドを打ちます。
pip install WeasyPrint
pipを最新化しろとメッセージが出たので、アップグレードします。
python3 -m pip install --upgrade pip
ソース
ざっくりソースを書きます。
views.py
from .models import Person from django.http import HttpResponse from django.template.loader import render_to_string from weasyprint import HTML import tempfile def generate_pdf(request): from django.template.loader import get_template # テンプレートを指定 html_template = get_template('testapp/scoringsheet_list.html') html_str = html_template.render({ #引数とかある場合は、ここに設定する。 'Member': Member, 'Scoringsheet': Scoringsheet, },request) pdf_file = HTML('http://127.0.0.1:8000/scoringsheet?event=4').write_pdf( # weasyprintではCSSを指定してあげないと参照してくれないようなので、必要なら指定する。 # 今回は特に使わないのでコメント # stylesheets=[ # CSS('/static/css/something.css') # ], ) response = HttpResponse(pdf_file, content_type='application/pdf') # ダウンロードした時のファイル名称を設定。 response['Content-Disposition'] = 'filename="scoringsheet.pdf"' return response
urls.py
urlpatterns = [ # weasyprint path('generate/pdf/', views.generate_pdf, name='generate_pdf'), ]
試しにPDF化実行すると、各種エラー発生
urlsに書いたアドレスにアクセス。
ローカルサーバーだと、以下のようなアドレスです。
http://127.0.0.1:8000/generate/pdf/
エラーが出ました。
django OSError: no library called "cairo" was found
cairoってのが無いようなので、サーバーを落としてHomebrewでインストールします。
brew install python3 cairo pango gdk-pixbuf libffi
再度サーバー起動。またエラー。
no library called "libcairo-2" was found cannot load library 'libcairo.so': dlopen(libcairo.so, 2): image not found cannot load library 'libcairo.2.dylib': dlopen(libcairo.2.dylib, 2): image not found cannot load library 'libcairo-2.dll': dlopen(libcairo-2.dll, 2): image not found
なんか、色々ネットで対処法を探しているとpython3系ならpip3でインストールしないといけない。らしいので再度weasyprintをインストール。
pip3 install WeasyPrint
必要かどうか不明ですが、ここでもう一度cairoをインストール。
brew install cairo
また別のエラーが出ました。
もしかしたら、前にも出ていたかもしれませんがここで気がつきました。
Error: The following formula [#<Dependency: "python@3.8" []>, #<Options: []>] cannot be installed as binary package and must be built from source. Install the Command Line Tools: xcode-select --install
xcodeがバーチャル環境にちゃんと入っていないのかな?
よくわかりませんが、サーバーを落としてxcodeをインストール。
xcode-select --install
再度サーバー起動。またエラー。
raise OSError(msg) OSError: cannot load library 'pango-1.0': dlopen(pango-1.0, 2): image not found. Additionally, ctypes.util.find_library() did not manage to locate a library called 'pango-1.0'
pangoってのが無いようなので、サーバー落としてpangoをインストール。
brew install pango
サーバー再起動。成功です。
PDF出力テスト
PDF出力するURLにアドレスにアクセスして、PDF出力テストします。
派手に文字化けしてしまいました。
(Djangoのテンプレート画面)(weasyprintでPDF出力結果)
日本語と数字が全滅です。
HTMLにはちゃんと文字コード指定をしてるのですが、関係ないようです。
ちなみに改ページしても、ヘッダはページごとについてきたので安心しました。
今後の課題
まずは上記の文字化けをなんとかしないといけません。
それが出来たら、A4で横向き(landscape)出力設定をしたいです。
現状調べたところ、よくわからないです。
まとめ
weasyprintはインストールが一つでは済まないのが難点です。
ソース自体はサンプルコードが結構落ちているので、とりあえずはなんとかなります。
しかし、細かい不具合についての対処法はあまり無いように感じました。この辺りは結構努力が必要そうです。
最後に、Djangoのテンプレート通りに出力はしてくれない様なのでCSSはweasyprint用にCSSはちゃんと指定した方が良いみたいです。
ついでに
(上記のソースでは関係ありませんが)ソースの書き方によっては、日本語があるとユニコードエラーが出るようなのでoutput.nameを以下のように変更。
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb5 in position 10: invalid start byte
output = open(output.name, 'r') ↓fix output = open(output.name, 'rb')