---
title: "Django で CSV を出力する"
version: 1.10
locale: ja
source: https://docs.djangoproject.com/ja/1.10/howto/outputting-csv/
canonical: https://djangodocs.dev/ja/1.10/howto/outputting-csv/
---
# Django で CSV を出力する

このドキュメントでは、Django のビューを使って動的に CSV (Comma Separated Values) を出力する方法を説明しています。そのためには、Python のCSV ライブラリか Django のテンプレートシステムを使います。

## Python の CSV ライブラリを使う

Python の標準ライブラリには CSV のライブラリ [`csv`](https://docs.python.org/3/library/csv.html#module-csv) が含まれています。Django でこのライブラリを使うコツは、[`csv`](https://docs.python.org/3/library/csv.html#module-csv) モジュールの CSV 生成機能がファイルライクオブジェクトに対して働くことを利用します。Django の [`HttpResponse`](/ja/1.10/ref/request-response/#django.http.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')
    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
```

コードとコメントが自分自身の意味を説明しているはずですが、いくつかの点には言及しておくべきでしょう。

- レスポンスは特別な MIME タイプ (`text/csv`) を受け取ります。これにより、ブラウザは、ドキュメントが HTML ではなく CSV ファイルであることを判断します。もしこの MIME タイプの設定を忘れると、ブラウザは出力を HTML と解釈し、ブラウザウィンドウに醜くて恐ろしいぐちゃぐちゃの文字列が現れてしまう恐れがあります。
- レスポンスには、追加の `Content-Disposition` ヘッダに CSV のファイル名を設定することができます。ファイル名はどんなものでも構いません。ここで指定した名前は、ブラウザが「別名で保存」ダイアログなどで使用します。
- CSV 生成の API に接続するのは簡単です: `response` を最初の引数として `csv.writer` に渡すだけです。`csv.writer` 関数は、ファイルライクのオブジェクトを要求しますが、 [`HttpResponse`](/ja/1.10/ref/request-response/#django.http.HttpResponse) のオブジェクトはこの要求にぴったりです。
- CSV ファイルの行ごとに、`writer.writerow` を呼んで、リストやタプルのような iterable オブジェクトを渡してください。
- CSV モジュールは引用を適切に処理するので、引用符やカンマでの文字列のエスケープについて心配する必要はありません。生の文字列を `writerow()` に渡すだけで適切に処理されます。

> **Python2 で Unicode を扱う**
>
> Python 2 の [`csv`](https://docs.python.org/3/library/csv.html#module-csv) モジュールは Unicode の入力をサポートしていません。Django は内部的に Unicode を使うので、[`HttpRequest`](/ja/1.10/ref/request-response/#django.http.HttpRequest) のようなソースから読み出された文字列は、問題となる可能性があります。これを解決するためにはいくつかの選択肢があります:
>
> - 全ての Unicode オブジェクトを手動でエンコードして、互換性のあるエンコーディングに変換する。
> - [csv module's examples section](https://docs.python.org/2/library/csv.html#examples) で提供されている `UnicodeWriter` クラスを使う。
> - [python-unicodecsv module](https://github.com/jdunck/python-unicodecsv) を使う。これは、Unicode を上手に処理するの [`csv`](https://docs.python.org/3/library/csv.html#module-csv) を一時的に置換することを狙いとします。
>
> より詳しくは、Python ドキュメントの [`csv`](https://docs.python.org/3/library/csv.html#module-csv) モジュールを参照してください。

### サイズの大きな CSV ファイルをストリーミングする

大きなサイズのレスポンスを生成するビューを取り扱うときには、代わりに Django の [`StreamingHttpResponse`](/ja/1.10/ref/request-response/#django.http.StreamingHttpResponse) の使用を考えてみてください。例えば、生成に長時間を要するファイルをストリーミングことで、サーバーがレスポンスを生成している間にタイムアウトしてしまうような接続でも、ロードバランサが接続をドロップすることを防げます。

この例では、Python のジェネレータを最大限使用して、サイズの大きな CSV ファイルの組み立てと伝達を効率的に扱います。

```
import csv

from django.utils.six.moves import range
from django.http import StreamingHttpResponse

class Echo(object):
    """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)
    response = StreamingHttpResponse((writer.writerow(row) for row in rows),
                                     content_type="text/csv")
    response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
    return response
```

## テンプレートシステムを使う

もしくは、[Django のテンプレートシステム](/ja/1.10/topics/templates/) を使って CSV を生成することもできます。Python の [`csv`](https://docs.python.org/3/library/csv.html#module-csv) モジュールの利便性には劣りますが、完全性のために提供されています。

考え方としては、テンプレートに項目のリストを渡すというものです。そして、テンプレートの [`for`](/ja/1.10/ref/templates/builtins/#std-templatetag-for) ループの中でカンマを出力させます。

以下の例は、上述の例と同じ CSV ファイルを生成します。

```
from django.http import HttpResponse
from django.template import loader, Context

def some_view(request):
    # Create the HttpResponse object with the appropriate CSV header.
    response = HttpResponse(content_type='text/csv')
    response['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 = Context({
        'data': csv_data,
    })
    response.write(t.render(c))
    return response
```

この例と上述の例の唯一の違いは、この例では CSV モジュールの代わりにテンプレートを呼び出していることです。残りのコード部分 -- 例えば `content_type='text/csv'` -- は同じです。

そして、以下のテンプレートのコードを用いて、テンプレート `my_template_name.txt` を作成しましょう。

```html+django
{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
{% endfor %}
```

このテンプレートはとても基本的なものです。与えられたデータを繰り返し処理し、行ごとに CSV の行を表示します。[`addslashes`](/ja/1.10/ref/templates/builtins/#std-templatefilter-addslashes) を使って、引用符に問題がないことを調べます。

## 他のテキストベースのフォーマット

ここで説明した CSV (特定の出力フォーマットの 1 つ)のような、フォーマット特有の説明は特にありません。あなたの望むテキストベースのフォーマットを出力するときには、ここで説明したテクニックを活用してみてください。また、任意のバイナリデータを生成するときにも、ここでのテクニックが参考になります; [Django で PDF を出力する](/ja/1.10/howto/outputting-pdf/) で例を参照してください。
