Вывод 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 .