Spec-Zone.ru › Django 4.2

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

В этом документе объясняется, как динамически выводить 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",
        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

При работе с представлениями, генерирующими очень большие ответы, вы можете рассмотреть использование 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)
    return StreamingHttpResponse(
        (writer.writerow(row) for row in rows),
        content_type="text/csv",
        headers={"Content-Disposition": 'attachment; filename="somefilename.csv"'},
    )

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

В качестве альтернативы вы можете использовать систему шаблонов Django для генерации CSV. Это более низкий уровень, чем использование удобного модуля 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 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 = {"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/4.2/howto/outputting-csv/

Spec-Zone.ru

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