revision-up-to: | 17812 (1.4) |
---|
このドキュメントでは、 Django のビューを使って動的に PDF ファイルを生成する 方法について説明します。 PDF を生成するには、優れたオープンソースの Python 用 PDF ライブラリである ReportLab を使います。
動的に PDF ファイルを生成できると、ユーザごとに違ったコンテンツの PDF を生 成するといった具合に、目的ごとに PDF 生成をカスタマイズできます。
例えば、 kusports.com では、March Madness contest の参加者向けに、 Django を使ってカスタマイズ可能な印刷むきの NCAA トーナメント試合表を PDF で生成し ていました。
ReportLab ライブラリは http://www.reportlab.org/oss/rl-toolkit/downlods/ から ダウンロードしてインストールします。
インストール方法は ユーザガイド (はからずも PDF ファイルですが) に書かれ ています。
インストールがうまく行っているか、 Python 対話シェルで import してみて確か めます:
>>> import reportlab
エラーを送出しなければ、インストールはうまくいっています。
Django を使った PDF 動的生成の鍵は、ファイル ReportLab の API がファイルラ
イクオブジェクトのように動作し、 Django の
HttpResponse
オブジェクトもまた、ファイルライクオブジェ
クトのように振舞うところにあります。
いわゆる “Hello World” サンプルを示します:
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def some_view(request):
# 適切な PDF 用応答ヘッダを持った HttpResponse オブジェクトを
# 作成します。
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
# レスポンスオブジェクトを出力「ファイル」にして、 PDF オブジェクト
# を作成します。
p = canvas.Canvas(response)
# PDF に描画します。 PDF 生成のキモの部分です。
# ReportLab の詳しい機能は ReportLab ドキュメントを参照してください。
p.drawString(100, 100, "Hello world.")
# PDF オブジェクトをきちんと閉じて終わり。
p.showPage()
p.save()
return response
コードとコメントを読めば一目瞭然ですが、いくつか注意しておいたほうがよいで しょう:
レスポンスの MIME タイプは application/pdf にします。これによ り、ブラウザにドキュメントが PDF であると指示します。 MIME タイプを指定しな いと、出力を HTML として解釈するので、ブラウザウィンドウに見苦しいごみのよう な出力が表示されてしまいます。
さらに、レスポンスオブジェクトには Content-Disposition
ヘッダを指
定しています。このヘッダは PDF ファイルの名前にします。ファイル名には
何を指定しても構いません。この名前は、ブラウザが「名前を付けて保存」
ダイアログなどで使います。
上の例では、 Content-Disposition
ヘッダは 'attachment; '
から
始まっています。ヘッダを 'attachment; '
で始めると、ウェブブラウ
ザは application/pdf
に対するデフォルトの操作を指定していても、
ダイアログパネルを出して、ドキュメントの処理方法を選択するようユーザ
に促します。以下のように 'attachment;'
を入れない場合、ブラウザは
デフォルトの設定を使って PDF を処理します:
response['Content-Disposition'] = 'filename=somefilename.pdf'
ReportLab API のフックは簡単です: response
を canvas.Canvas
の第一引数に指定します。 Canvas
クラスはファイルライクオブジェク
トを扱うようになっているので、 django.http.HttpResponse
オブ
ジェクトを使えます。
PDF オブジェクト (ここでは p
) を生成した後は、 response
では
なく p
を使って PDF 生成メソッドを呼び出していることに注意して下
さい。
最後に必ず showPage()
を呼び出し、 PDF ファイルを save()
して
ください。
ReportLab を使って複雑な PDF を作成したければ、一時的なファイルの保存に
cStringIO
ライブラリを使ってください。 cStringIO
ライブラリはこ
のような目的に対してとても効率的なファイルライクオブジェクトを提供します。
cStringIO
で書き直した上の “Hello World” の例を示します:
# cStringIO が使えない環境では StringIO にフォールバックします
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def some_view(request):
# 適切な PDF 用応答ヘッダを持った HttpResponse オブジェクトを
# 作成します。
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
buffer = String()
# StringIO オブジェクトを出力「ファイル」にして、 PDF オブジェクト
# を作成します。
p = canvas.Canvas(buffer)
# PDF に描画します。 PDF 生成のキモの部分です。
# ReportLab の詳しい機能は ReportLab ドキュメントを参照してください。
p.drawString(100, 100, "Hello world.")
# PDF オブジェクトをきちんと閉じます。
p.showPage()
p.save()
# StringIO バッファの値を取り出して、レスポンスオブジェクトに
# 書き込みます。
pdf = buffer.getvalue()
buffer.close()
response.write(pdf)
return response
system
や
popen
のようなシェルを実行して、出力を Python から取り出せます。ここで示した例の大部分は、 PDF 固有の内容ではないことに注意してください。
PDF に関する部分といえば reportlab
くらいのものです。同じようなテクニッ
クを使えば、 Python のライブラリが扱えるどんなフォーマットのデータでも生成
できるのです。もう一つの例として、テキストベースの出力をしている
Django で CSV を出力する も参照してください。
Oct 26, 2017