Djangoを使用したCSVの出力—Djangoドキュメント

提供:Dev Guides
< DjangoDjango/docs/3.2.x/howto/outputting-csv
移動先:案内検索

DjangoでCSVを出力する

このドキュメントでは、Djangoビューを使用してCSV(カンマ区切り値)を動的に出力する方法について説明します。 これを行うには、PythonCSVライブラリまたはDjangoテンプレートシステムのいずれかを使用できます。

PythonCSVライブラリの使用

Pythonには、CSVライブラリcsvが付属しています。 Djangoで使用するための鍵は、csvモジュールのCSV作成機能がファイルのようなオブジェクトに作用し、Djangoの HttpResponse オブジェクトがファイルのようなオブジェクトであるということです。

次に例を示します。

import csv
from django.http import HttpResponse

def some_view(request):
    # Create the HttpResponse object with the appropriate CSV header.
    response = HttpResponse(
        content_type='text/csv',
        headers={'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

コードとコメントは自明である必要がありますが、いくつか言及する価値があります。

  • 応答は、特別なMIMEタイプ text / csv を取得します。 これにより、ドキュメントがHTMLファイルではなくCSVファイルであることがブラウザに通知されます。 これをオフのままにすると、ブラウザはおそらく出力をHTMLとして解釈し、ブラウザウィンドウに醜い恐ろしいgobbledygookが表示されます。
  • 応答は、CSVファイルの名前を含む追加のContent-Dispositionヘッダーを取得します。 このファイル名は任意です。 好きなように呼んでください。 「名前を付けて保存…」ダイアログなどでブラウザによって使用されます。
  • csv.writerの最初の引数としてresponseを渡すことにより、CSV生成APIにフックできます。 csv.writer関数はファイルのようなオブジェクトを想定しており、 HttpResponse オブジェクトは適切です。
  • CSVファイルの各行について、writer.writerowを呼び出し、 iterable を渡します。
  • CSVモジュールが引用符を処理するため、引用符やカンマを含む文字列をエスケープする必要はありません。 writerow()を生の文字列に渡すと、正しい処理が実行されます。

大きなCSVファイルのストリーミング

非常に大きな応答を生成するビューを処理する場合は、代わりにDjangoの StreamingHttpResponse の使用を検討することをお勧めします。 たとえば、生成に時間がかかるファイルをストリーミングすることで、サーバーが応答を生成している間にタイムアウトした可能性のある接続をロードバランサーがドロップするのを回避できます。

この例では、Pythonジェネレーターを最大限に活用して、大きなCSVファイルのアセンブリと送信を効率的に処理します。

import csv

from django.http import StreamingHttpResponse

class Echo:
    """An object that implements just the write method of the file-like
    interface.
    """
    def write(self, value):
        """Write the value by returning it, instead of storing in a buffer."""
        return value

def some_streaming_csv_view(request):
    """A view that streams a large CSV file."""
    # Generate a sequence of rows. The range is based on the maximum number of
    # rows that can be handled by a single sheet in most spreadsheet
    # applications.
    rows = (["Row {}".format(idx), str(idx)] for idx in range(65536))
    pseudo_buffer = Echo()
    writer = csv.writer(pseudo_buffer)
    return StreamingHttpResponse(
        (writer.writerow(row) for row in rows),
        content_type="text/csv",
        headers={'Content-Disposition': 'attachment; filename="somefilename.csv"'},
    )

テンプレートシステムの使用

または、 Djangoテンプレートシステムを使用してCSVを生成することもできます。 これは、便利なPython csvモジュールを使用するよりも低レベルですが、完全を期すためにソリューションをここに示します。

ここでの考え方は、アイテムのリストをテンプレートに渡し、テンプレートに:ttag: `for` ループでコンマを出力させることです。

上記と同じCSVファイルを生成する例を次に示します。

from django.http import HttpResponse
from django.template import loader

def some_view(request):
    # Create the HttpResponse object with the appropriate CSV header.
    response = HttpResponse(
        content_type='text/csv'
        headers={'Content-Disposition': 'attachment; filename="somefilename.csv"'},
    )

    # The data is hard-coded here, but you could load it from a database or
    # some other source.
    csv_data = (
        ('First row', 'Foo', 'Bar', 'Baz'),
        ('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"),
    )

    t = loader.get_template('my_template_name.txt')
    c = {'data': csv_data}
    response.write(t.render(c))
    return response

この例と前の例の唯一の違いは、この例ではCSVモジュールの代わりにテンプレートの読み込みを使用していることです。 content_type='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行を表示します。 :tfilter: `addslashes` テンプレートフィルターを使用して、引用符に問題がないことを確認します。


その他のテキストベースの形式

ここではCSVに固有のものはあまりなく、特定の出力形式のみであることに注意してください。 これらの手法のいずれかを使用して、夢のようなテキストベースの形式を出力できます。 同様の手法を使用して、任意のバイナリデータを生成することもできます。 例については、 Django を使用したPDFの出力を参照してください。