Spec-Zone.ru › Django 6.0

Как создать вывод CSV

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

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

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

В этом примере мы используем генераторы 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"'},
    )

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

В качестве альтернативы для создания CSV можно использовать систему шаблонов Django. Это решение более низкоуровневое, чем использование удобного модуля Python csv, но для полноты картины мы приводим его здесь.

Идея заключается в том, чтобы передать шаблону список элементов и выводить запятые в цикле 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 hardcoded 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 для каждой строки. Он использует фильтр шаблонов addslashes, чтобы избежать проблем с кавычками.

Другие текстовые форматы

Обратите внимание, что здесь почти нет ничего специфичного для CSV — только формат вывода. Любой из этих способов можно использовать для вывода любого текстового формата, который вам нужен. Аналогичный подход позволяет создавать произвольные двоичные данные; пример приведён в разделе Как создавать PDF-файлы.

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

Spec-Zone.ru

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