Исходные данные:
- Джанго проект, база данных
- Есть сложный запрос, с большим количеством данных. Часто запрос моно описать моделями, чтобы усложнить задачу, будем писать сырой запрос mysql
- Необходимо надежно выгрузить в CSV. Может даже миллионы строк
- первой строкой в выгрузке будет хедер с названием столбцов
- кастомный разделитель полей, например точка с запятой
1) views.py
- добавляем необходимые импорты в начале кода
from django.http import StreamingHttpResponse import csv
- файло-подобный объект, который понадобится для добавления строк запроса в выходной CSV
class Echo: def write(self, value): return value
- сам метод выгрузки в csv
def download_csv(filename, rows): pseudo_buffer = Echo() # используем кастомный разделитель полей - точка с запятой, по умолчанию, разделитель - запятая writer = csv.writer(pseudo_buffer, delimiter=';') return StreamingHttpResponse( ( writer.writerow(row) for row in rows ), content_type="text/csv", headers={'Content-Disposition': 'attachment; filename="' + filename + '.csv"'}, )
- и пример его использования:
def download_orders_for_user(request): # например, запрос всех заказов пользователей с айдишниками от 1 до 10000 и суммой больше 10 query = """ SELECT order.number, order.date, order.sum, order.status FROM order LEFT JOIN user ON user.id = order.user_id WHERE user BETWEEN 1 and 10000 AND order.sum > 10 """ with connections["default"].cursor() as cursor: cursor.execute(query) rows = cursor.fetchall() # формируем имя файла filename = 'orders_for_users' # первой строкой у нас будет хедер с названием столбцов header_row = (('Номер', 'Дата', 'Сумма', 'Статус'),) rows = header_row + rows return download_csv(filename, rows)
2) urls.py
Зададим 2 урла:
- для страницы, со ссылкой на выгрузку
- для запроса выгрузки (нажатие на ссылку выгрузки)
… urlpatterns = [ … path('download_page/', views.download_page, name='download_page'), path('download_page/csv/', views.download_orders_for_user, name='download_orders_for_user'), ]
3) создадим темплейт с HTML страничкой
для размещения ссылки скачивания и проверки работы наших скриптов
download_page.html
со следующим содержимым:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Download SCV</title> </head> <body> <div> <h4>Скачать заказы пользователей: </h4> <a id="download" href="csv/">CSV</a> </div> </body> </html>
Это все!