PDFファイルを作成する¶
このドキュメントでは、Django のビューを使用して PDF ファイルを動的に出力する方法を説明します。これは、優れたオープンソースの Python PDF ライブラリ ReportLab により可能になっています。
PDF ファイルを動的に生成する利点は、異なる目的のためにカスタマイズされた PDF を作成できることです。たとえば、異なるユーザーや異なるコンテンツを使用して生成できます。
たとえば、kusports.com では、March Madness コンテストに参加する人たちのために、カスタマイズされたプリンター向けの NCAA トーナメントブラケットを PDF ファイルとして生成するのに Django が使われていました。
ReportLab をインストールする¶
ReportLab ライブラリは、PyPI で利用できます。ユーザーガイド (偶然ではなく PDF で提供されています) もダウンロードして利用できます。ReportLab は pip
により次のコマンドでインストールできます。
$ python -m pip install reportlab
...\> py -m pip install reportlab
Python の対話的インタープリタ内でインポートすることでインストールをテストします。
>>> import reportlab
このコマンドが何もエラーを起こさなければ、インストールは機能しています。
ビューを書く¶
Django で PDF を動的に生成するときに重要な点は、ReportLab API がファイルライクなオブジェクトとして振る舞い、Django の FileResponse
オブジェクトがファイルライクなオブジェクトを受け取るということです。
ここに、"Hello World"の例を示します:
import io
from django.http import FileResponse
from reportlab.pdfgen import canvas
def some_view(request):
# Create a file-like buffer to receive PDF data.
buffer = io.BytesIO()
# Create the PDF object, using the buffer as its "file."
p = canvas.Canvas(buffer)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
# FileResponse sets the Content-Disposition header so that browsers
# present the option to save the file.
buffer.seek(0)
return FileResponse(buffer, as_attachment=True, filename="hello.pdf")
コードとコメントが自分自身の意味を説明しているはずですが、いくつかの点には言及しておくべきでしょう。
- レスポンスはファイル名の拡張子に基づいて自動的にMIMEタイプ application/pdf を設定します。これはブラウザに、ドキュメントがHTMLファイルや一般的な application/octet-stream バイナリコンテンツではなく、PDFファイルであることを伝えます。
as_attachment=True
がFileResponse
に渡されると、適切なContent-Disposition
ヘッダが設定され、ウェブブラウザはそのマシンでデフォルトが設定されていたとしても、そのドキュメントをどのように扱うかを確認するダイアログボックスをポップアップするようになります。もしas_attachment
パラメータが省略された場合、ブラウザはPDFを扱うために設定されたプログラムやプラグインを使ってPDFを扱います。- 任意の
filename
パラメータを指定できます。これはブラウザの "名前を付けて保存" ダイアログで使用されます。 - ReportLab API にフックできます:
canvas.Canvas
の第一引数に渡されたバッファと同じバッファをFileResponse
クラスに渡すことができます。 - 後続のPDF生成メソッドはすべて、PDFオブジェクト(この場合は
p
)に対して呼び出され、buffer
に対して呼び出されるのではないことに注意してください。 - 最後に、PDFファイル上で
showPage()
とsave()
を呼び出すことが重要です。
注釈
ReportLabはスレッドセーフではありません。一部のユーザーからは、多くの人が同時にアクセスするPDF生成Djangoビューを構築する際に奇妙な問題が発生するとの報告があります。
ほかのフォーマット¶
これらの例には PDF 固有のものはあまりないことに注意してください -- reportlab
を使った部分だけです。同じようなテクニックを使って、Pythonのライブラリがあれば任意のフォーマットを生成できます。また、 CSVを出力する にも別の例とテキストベースのフォーマットを生成するときに使えるテクニックがあります。
参考
Django Packagesは、DjangoからPDFファイルを生成するのに役立つ パッケージの比較一覧 を提供しています。