Export Excel file using celery

I will try my best with the example you given.

Assume you have this model:

# models.py
from django.db import models
from django.utils.translation import gettext_lazy as _

class FilmExportRequest(models.Model):
    user = models.ForeignKey(
        to="users.User", # or wherever is your user model
        on_delete=models.CASCADE,
        related_name="film_export_requests",
        verbose_name=_("User"),
        help_text=_("The user that requested the export"),
    )
    report = models.FileField(
        verbose_name=_("Report"),
        upload_to="films/exports",
        help_text=_("The report file will be populated after a few moments"),
        null=True,
        blank=True,
    )
    created_at = models.DateTimeField(
        verbose_name=_("Created at"),
        help_text=_("When the report has been created"),
        null=True,
        blank=True,
        auto_now_add=True,
    )
    started_at = models.DateTimeField(
        verbose_name=_("Started at"),
        help_text=_("When the report has started to be processed"),
        null=True,
        blank=True,
    )
    finished_at = models.DateTimeField(
        verbose_name=_("Finished at"),
        help_text=_("When the report has finished"),
        null=True,
        blank=True,
    )

    class Meta:
        verbose_name = _("Film Export Request")
        verbose_name_plural = _("Film Export Requests")

Then you would have this task.

from django.utils import timezone

@shared_task
def export_films_excel(film_export_request_id):
    film_export_request = FilmExportRequest.objects.get(pk=film_export_request_id)
    film_export_request.started_at = timezone.now()
    film_export_request.save()

    # Your code as-is
    wb = xlwt.Workbook(encoding='utf-8')
    ws = wb.add_sheet('Filmes')

    row_num = 0
    columns = ['Id', 'Nome', 'Descrição', 'Gostaria de Assistir']

    for col_num in range(len(columns)):
        ws.write(row_num, col_num, columns[col_num])

    row_num = 1
    for film in Film.objects.filter(user=film_export_request.user):
        ws.write(row_num, 0, film.id)
        ws.write(row_num, 1, film.name)
        ws.write(row_num, 2, film.description)
        ws.write(row_num, 3,
            'Gostaria' if film.would_like is True else 'Assistido')
        row_num += 1

    # You would need to figure it out this write on your own
    # wb.save(response)

    film_export_request.finished_at = timezone.now()
    film_export_request.save()

Then on your view:

@method_decorator(
    login_required(login_url='authentication:login', redirect_field_name='next'),
    name='dispatch'
)
class ExportFilms(View):
    def get(self, request):

        export_request = FilmExportRequest(user=request.user)
        export_request.save()
        export_films_excel.apply_async(kwargs={"film_export_request_id": export_request.id})
        return render(request, "some_template", context={"export_request": export_request})

The example is not functional as-is but will give you a pretty good start.

1 Like