revision-up-to: | 17812 (1.4) |
---|
このドキュメントでは、 Django のビューを使って動的に CSV (Comma Separated Values: カンマ区切りのフィールドデータ) ファイルを生成する方法について説明 します。 CSV の生成には Python CSV ライブラリ、または Django テンプレートシス テムが使えます。
Python には CSV ライブラリモジュール csv
がついてきます。Django で
csv
を使う上での鍵は、モジュールの CSV 生成機能がファイルライクオ
ブジェクトを扱えることと、 Django の HttpResponse
オ
ブジェクトがファイルライクオブジェクトであることです。
一例を示します:
import csv
from django.http import HttpResponse
def some_view(request):
# 適切な CSV 用ヘッダとともに HttpResponse オブジェクトを生成します。
response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename=somefilename.csv'
writer = csv.writer(response)
writer.writerow(['First row', 'Foo', 'Bar', 'Baz'])
writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"])
return response
コードとコメントを読めば一目瞭然ですが、いくつか注意しておいたほうがよいで しょう:
Content-Disposition
ヘッダを指
定しています。このヘッダは CSV ファイルの名前にします。ファイル名には
何を指定しても構いません。この名前は、ブラウザが「名前を付けて保存」
ダイアログなどで使います。response
を csv.writer
の第
一引数に指定します。 csv.writer
クラスはファイルライクオブジェク
トを扱うようになっているので、 HttpResponse
オ
ブジェクトを使えます。writer.writerow
を呼び出します。writerow()
に渡せば、モジュールが正しく処理してくれます。Python の csv
モジュールは Unicode の入力をサポートしていません。
Django は内部的に Unicode を使うので HttpRequest
のよう
なソースから文字列を読み込むことは潜在的に問題を抱えていることになります。この
問題の対処方法はいくつかあります:
UnicodeWriter
クラスを使
います。csv
モジュールを容易に置き換えることを目的にしています。もっと情報が必要なら csv
モジュールのドキュメントを参照してください。
csv
を使う代りに Django テンプレートシステム
を使っても CSV を生成できます。この方法よりも csv`
モジュールを使った方
がより高水準で実現できますが、完全さのために紹介しておきます。
基本的な考え方は、テンプレートに要素リストを渡し、テンプレート上の
for
ループの中でコンマとともに出力するというものです。
上と同じ CSV ファイルを生成する例を示します:
from django.http import HttpResponse
from django.core.template import loader, Context
def some_view(request):
# 適切な CSV 用応答ヘッダを持った HttpResponse オブジェクトを
# 作成します。
response = HttpResponse(mimetype='text/csv')
response['Content-Disposition'] = 'attachment; filename=somefilename.csv'
# ここではデータをハードコードしていますが、実際にはデータベースな
# のデータソースから取り出せます。
csv_data = (
('First row', 'Foo', 'Bar', 'Baz'),
('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"),
)
t = loader.get_template('my_template_name.html')
c = Context({
'data': csv_data,
})
response.write(t.render(c))
return response
前節の例との違いは、 CSV モジュールの代りにテンプレートをロードしている点だ
けです。それ以外のコード、例えば mimetype='text/csv'
のような部分はまっ
たく同じです。
次に、 my_template_name.txt
というテンプレートを以下のように書きます:
{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
{% endfor %}
このテンプレートはきわめて基本的なものです。テンプレートは指定されたデータ
に渡って繰り返し CSV の各行を表示してゆきます。クオートで問題が生じないよう、
addslashes
テンプレートフィルタを使っています。データに引用符
(一重と二重の両方) が入っていないと保証できる場合は addslashes
フィルタを外してもかまいません。
ここで示した例の大部分は、 CSV 固有の内容ではないことに注意してください。 CSV に関する部分といえば、出力形式くらいのものです。同じようなテクニックを 使えば、 どんなテキスト形式のデータでも生成できるのです。バイナリデータを生 成するときにも、同じようなテクニックを使えます。 Django で PDF を出力する を参照してください。
Oct 26, 2017