Вывод CSV с помощью Django

В этом документе объясняется, как динамически выводить CSV (значения, разделенные запятыми), используя представления 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',
        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"'},
    )

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

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

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

Copyright ©2021 All rights reserved