【问题标题】:Django, Celery: Retrieving a file generated asynchronouslyDjango,Celery:检索异步生成的文件
【发布时间】:2019-04-01 14:20:58
【问题描述】:

我有一个页面 (foo.com/process),您可以在其中生成数据报告。有时需要生成的数据量很大,所以需要一段时间。因此,我做了一个 Celery 任务来处理 PDF 生成方面的事情。单击 PDF 图像时会生成报告:

<i data-processid="{{process.id}}" data-filename="{{process.pdf}}" class="fas fa-file-download getPdf"></i>

当你点击那个 FA 图标时,一个 AJAX POST 请求被发送到 Django 视图:

$(".getPdf").on('click', function(event) {

    var thisId = $(this).data('processid');
    var filename = $(this).data('filename');

    $.post({
        url: "{% url 'process' %}", // Points to foo.com/process
        data: {
            csrfmiddlewaretoken: "{{ csrf_token }}",
            id: thisId
        },
        success: function(data) {
            ... handle sucess
        },
        error: function(data) {
            ... handle error
        },
        traditional: true
    }).done();

    downloadPdf(filename);

    function downloadPdf(filename) {
        setTimeout(function() { window.location.href = filename; }, 10000);

    };
});

AJAX函数将请求发送到后端启动Celery进程生成PDF,然后立即调用downloadPfd函数,这只是一个延迟函数设置为(我以为是)下载方式通过 JavaScript 生成文件。超时时间足够生成文件了。

即使 PDF 文件已创建并位于主项目文件夹中,我也找不到文件(我稍后会在确保它正常工作后将其移动到 Django 中的 MEDIA 文件夹中.

现在,我最好通过 Django 来做这件事,这是我尝试的另一条路线。

在我的 Django 视图的 POST 部分,我有以下内容:(

class ProcessView(generic.DetailView):
    template_name = 'pages/process.html'

    def get(self, request):
        # GET stuff happens
        return render(request, self.template_name, {'process_form': process_form, 'process': process_list})

    def post(self, request):
            # Get the Process ID from the incoming request
            process_id = request.POST.get('id')

            # Get relevant objects and queries
            ... python and DB stuff ...

            # Fire off a Celery task to generate the PDF file asynchronously
            task = create_pdf.delay(sensor, range_period)

            return HttpResponseRedirect(self.request.path_info, {"task_id": task.task_id })

POST 部分全部有效。我单击一个按钮,它会发送创建一个 Celery 任务的 AJAX POST,该任务会生成一个文件。我似乎无法在前端获得task_id,即使它正在生成。

我感到困惑的部分是如何使用前端的 Celery task.task_id 定期轮询我的 Django 视图以检查 PDF 文件是否已生成,然后如何下载所述 PDF。我可以访问文件名和任务 ID。

我正在尝试关注this short tutorial,但我不太清楚其中的脚本部分(我不太擅长 JS),所以我不太确定如何处理“定期检查”如果文件存在,如果存在,请下载”部分,因为他似乎在使用基于函数的视图,而我在我的项目中使用基于类的视图。

【问题讨论】:

    标签: javascript ajax django pdf celery


    【解决方案1】:

    你这里有很多缺失的部分,所以我将回答第一个缺失的部分:

    1. 要从 ajax 帖子中获取 task_id,您的视图应返回 JsonResponse
    
    return JsonResponse({
        'task_id': task_id
    })
    
    1. 您的 javascript ajax 成功处理程序应从通常在 success 处理程序中返回的响应中解压缩该 task_id。

    2. 然后,您的 javascript 代码应该定期轮询一个单独的 django 视图,该视图可以检索 celery 任务的结果(可能是文件名)以返回生成的 PDF 的文件名。

    【讨论】:

      猜你喜欢
      • 2019-01-03
      • 1970-01-01
      • 2013-12-21
      • 2011-06-05
      • 2020-05-08
      • 2011-11-22
      • 2017-11-15
      • 2020-11-28
      • 2016-12-13
      相关资源
      最近更新 更多