Spec-Zone.ru › Django 1.8

Вывод CSV с Django

Этот документ объясняет, как динамически выводить CSV (Comma Separated Values) с помощью представлений Django. Для этого можно использовать либо библиотеку Python CSV, либо систему шаблонов Django.

Использование библиотеки Python CSV

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')
    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. Это сообщает браузерам, что документ является файлом CSV, а не HTML. Если этого не сделать, браузеры, вероятно, интерпретируют вывод как HTML, что приведёт к некрасивому, пугающему результату в окне браузера.
  • Ответ получает дополнительный Content-Disposition заголовок, который содержит имя файла CSV. Это имя файла произвольное; назовите его как хотите. Оно будет использоваться браузерами в диалоге «Сохранить как…» и т. д.
  • Подключение к API генерации CSV простое: достаточно передать response в качестве первого аргумента csv.writer. Функция csv.writer ожидает объект, подобный файлу, и объекты HttpResponse подходят.
  • Для каждой строки в файле CSV вызывается writer.writerow, передавая ему итерируемый объект, такой как список или кортеж.
  • Модуль CSV позаботится о кавычках, поэтому вам не нужно беспокоиться о экранировании строк с кавычками или запятыми в них. Просто передайте writerow() ваши исходные строки, и он сделает всё правильно.

Обработка Unicode в Python 2

Модуль Python 2 csv не поддерживает ввод Unicode. Поскольку Django использует Unicode внутри, это означает, что строки, считанные из таких источников, как HttpRequest, потенциально проблематичны. Есть несколько вариантов решения этой проблемы:

  • Вручную кодировать все объекты Unicode в совместимое кодирование.
  • Использовать класс UnicodeWriter, предоставленный в разделе примеров модуля csv.
  • Использовать модуль python-unicodecsv, который призван быть прямым аналогом csv и элегантно обрабатывать Unicode.

Для получения дополнительной информации см. документацию Python по модулю csv.

Потоковая передача больших файлов CSV

При работе с представлениями, генерирующими очень большие ответы, вы можете рассмотреть использование StreamingHttpResponse Django. Например, передавая файл, на генерацию которого требуется много времени, можно избежать того, что балансировщик нагрузки разорвёт соединение, которое могло бы иначе выйти из строя во время генерации ответа сервером.

В этом примере мы полностью используем генераторы 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 для генерации CSV. Это более низкоуровневый подход, чем использование удобного модуля Python csv, но решение представлено здесь для полноты.

Идея заключается в передаче списка элементов в шаблон и получении вывода запятых в цикле 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, с этим кодом шаблона:

{% 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 для примера.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.8/howto/outputting-csv/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API