Spec-Zone.ru › Django 2.0

Вывод CSV с Django

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

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

Python поставляется с библиотекой CSV, csv. Ключевым моментом при ее использовании с Django является то, что возможности создания CSV в модуле csv работают с объектами, похожими на файлы, а объекты HttpResponse Django являются объектами такого типа.

Вот пример:

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() ваши исходные строки, и он сделает все правильно.

Потоковая передача больших файлов 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)
    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 Context, loader

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/2.0/howto/outputting-csv/

Spec-Zone.ru

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