Генерация CSV на Django

Здесь описывается как генерировать CSV (Comma Separated Values)с помощью представлений Django. Для этого нам понадобится библиотека для работы с CSV или шаблоны Django.

Использование библиотеки для работы с CSV

Python поставляется с библиотекой csv. Фишка в том, что этот модуль работает с файловыми объектами, которым как раз и является 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

Код и комментарии должны быть понятны, но на некоторые вещи стоит обратить внимание:

  • Ответу устанавливается определённый тип text/csv, этим мы говорим браузеру, что передаём файл в формате CSV, а не HTML. Если этого не сделать, то браузер будет пытаться отобразить документ как HTML, что может испугать пользователя.

  • Ответ также имеет дополнительный заголовок Content-Disposition, в котором содержится имя файла. Оно будет подставлено в окне сохранения файла.

  • Для генерации CSV просто передайте response первым аргументом в csv.writer. Вообще, в csv.writer можно передавать любой файловый объект.

  • Для каждой строки в CSV файле вызовите writer.writerow, передав итерируемый объект (список или тьюпл).

  • Модуль для работы с CSV сам умеет экранировать спецсимволы, так что просто передавайте в writerow() свои данные.

Поддержка Unicode

В Django работа ведётся со строками формата Unicode, однако csv их не поддерживает. Вот несколько вариантов решения проблемы:

  • Ручная перекодировка всех Unicode объектов.

  • Использование UnicodeWriter, который описан в csv module’s examples section.

  • Использование python-unicodecsv module, который приходит на замену csv. Там с Unicode всё отлично.

За подробной информацией можно обратиться к документации по модулю csv.

Использование шаблонов

Однако, вы можете использовать Django template system для генерации CSV. Это низкоуровневое решение представлено здесь для полноты картины.

Суть в том, чтобы обработать список элементов вашим шаблоном и вывести в цикле с помощью, например, for.

Ниже пример реализации:

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

Единственное отличие между этим примером и предыдущим состоит в том, что используется шаблон Django, а не модуль 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 для каждого элемента. В нём используется фильтр addslashes, так что проблем с экранированием символов быть не должно.

Остальные текстовые форматы

Обратите внимание, что специфики именно CSV здесь нет. Подобным образом можно работать с остальными форматами: как текстовыми, так и бинарными (например, Генерация PDF на Django).