Django Экспорт Excel Сохранить файл на сервере (Celery + RabbitMQ)

У меня есть представление Django, которое экспортирует файл Excel и предлагает диалог загрузки, когда файл готов. Я устанавливаю Celery и RabbitMQ, чтобы сделать эту задачу фоновой. Это означает, что файл Excel не будет предложено загрузить, но я хотел бы сохранить его где-то в машине, чтобы пользователь мог позже перейти на страницу и загрузить его.

Пример:

Перейти на страницу "Список" -> Нажать на "Экспорт" -> Получить сообщение: "Ваш файл скоро будет готов" -> Пользователь переходит на страницу "Загрузки" -> Находит файл в списке -> Нажимает на загрузку.

Итак, процесс для меня сейчас заключается в создании новой модели:

class Export(models.Model):
    dossier = models.ForeignKey(
        Dossier,
        related_name="Export",
        on_delete=models.CASCADE,
        default=None,
        editable=False,
    )
    timestamp = models.DateTimeField(auto_now_add=True, editable=False)
    file = models.FileField(
        upload_to=get_rapport_filename, verbose_name="Fichiers Excel"
    )

    def __str__(self):
        return "%s - %s" % (self.dossier, self.timestamp)

    class Meta:
        verbose_name = "Excel Report"
        verbose_name_plural = "Excel Reports"

А это код, который генерирует файл Excel:

@shared_task
def export_dossiers_factures(request):
    dossier_queryset = Dossier.objects.filter(status_admin="Facturé")
    today = str(date.today())
    response = HttpResponse(
        content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
    )
    response["Content-Disposition"] = (
        "attachment; filename=" + today + "-dossiers_factures.xlsx"
    )
    workbook = Workbook()

    # Get active worksheet/tab
    worksheet = workbook.active
    worksheet.title = "Dossiers facturés"

    # Define the titles for columns
    columns = [
        "Numéro",
        "Créé le",
        "Assurance",
        "Prestataire",
        "Matricule",
        "N° de BL",
        "N° de Facture",
        "Date de mise à jour",
    ]

    row_num = 1

    # Assign the titles for each cell of the header
    for col_num, column_title in enumerate(columns, 1):
        cell = worksheet.cell(row=row_num, column=col_num)
        cell.value = column_title

    # Iterate through all movies
    for dossier in dossier_queryset:
        row_num += 1

        # Define the data for each cell in the row
        row = [
            dossier.numero,
            str(dossier.date_posted)[:10],
            dossier.assurance.name,
            dossier.created_by.user.username,
            dossier.matricule,
            dossier.bl,
            dossier.invoice,
            str(dossier.date_updated)[:10],
        ]

        # Assign the data for each cell of the row
        for col_num, cell_value in enumerate(row, 1):
            cell = worksheet.cell(row=row_num, column=col_num)
            cell.value = cell_value

    workbook.save(response)

    return response

Я хочу заменить return response на что-то, что сохраняет файл в каком-то месте и создает объект, указывающий на этот файл.

Я сделал примерно то же самое, что и вы, и сделал это таким образом :

Сначала я создаю свой файл и пишу в нем все, что хочу, так что в вашем случае, что-то вроде этого :

filepath = f'/filepath_to/{today}-dossiers_factures.xlsx'
workbook = Workbook(filepath)
... # Whatever you want to do with your file

После того, как вы создали файл, вам просто нужно получить его с помощью FileReponse :

response = FileResponse(open(filepath, 'rb'))
response['Content-Disposition'] = f"attachment; filename={today}-dossiers_factures.xlsx"
return response

В этом случае вы скачиваете файл, который был сохранен в том месте, куда вы его положили, вместо того, чтобы просто создать файл и вернуть его.

Надеюсь, я понял, чего вы хотели, и это ответ на ваш вопрос :)

Вернуться на верх