向客户端发送有关视图中长时间运行任务的进度的更新

Posted

技术标签:

【中文标题】向客户端发送有关视图中长时间运行任务的进度的更新【英文标题】:Sent update to client about progress of a long running task from view 【发布时间】:2019-03-14 07:16:06 【问题描述】:

我的网站上有一个页面,用户可以在其中使用 ajax 上传 xlsx 文件,在后端我读取文件,进行一些处理并开始将其行一一插入到我的数据库中。如果用户上传的文件非常大,在数据库中输入新值可能需要一段时间。因此,我想在他们的屏幕上为用户提供实时进度更新,例如。 -

Found 100 rows of data
Interesting 1/100.
Interesting 2/100.
...
Interesting 100/100.
Done.

我的观点:

import pandas as pd

def myView(self, request):
    """Handle POST requests, save all data provided in excel file."""
    excel_file = request.FILES.get('excel_one')
    excel_df = pd.read_excel(excel_file)
    data_format = ['Option_1', 'Option_2', 'Option_3', 'Option_4',]
    try:
        formatted_df = excel_df[data_format]
    except KeyError as error:
        return JsonResponse('success': False, 'message': str(error), )
    # forloop to create model objects
    for i, v in formatted_df.iterrows():
        # do a lot of data validating and stuff first
        MyModels.objects.create(arguments)
        print(f'Created object i+1/len(formatted_df)!'  # Want to to be sent to html page in real time
    return JsonResponse('success': True, )

我正在发出这样的 ajax 请求:

$.ajax(  // variables url, data, etc. contain the expected stuff
    async: false,
    url: url,
    method: "POST",
    data: data,
    success: function(d)
        if(data.success)
            console.log(d);
         
         else
             $('.log').append('<p><b>Error:</b> '+ d.message +'</p>')
         
     ,
     cache: false,
     contentType: false,
     processData: false
);

在数据库中保存数据和其他一切都按预期工作,但我只是不知道如何将实时更新发送到 ajax。我能想到的一种可能的解决方案是实现 Web 套接字而不是普通的 http 请求,但我有点着急,所以有什么方法可以用简单的 js 和 django 来实现。

【问题讨论】:

【参考方案1】:

Celery 会在这里提供帮助。

只需为我们耗时的任务编写一个函数,将其设置为 celery 任务 立即返回进程 ID 或文件作为对第一个 API 的响应 使用此 ID 从您的 ajax 轮询第二个 API,在此 API 上获得预期结果

请注意:请勿将任何 HTTP 请求保持打开超过特定时间段,这将严重影响性能。

【讨论】:

【参考方案2】:

如果你不想求助于WebSocket,你可以试试:

快速而肮脏的方法:让您的 JS 轮询另一个 API 视图以检查状态 你听说过StreamingHttpResponse吗?我从未使用过它,但可能值得一试。你可以看一个例子here。

【讨论】:

不是 js 的粉丝,所以我会先尝试StreamingHttpResponse,如果一切顺利,我会接受你的回答。 我不确定这实际上会有多大帮助,从外观上看,我认为你必须做一些解析客户端... 我最终使用了 websockets,因为我的项目的其他部分也需要它。

以上是关于向客户端发送有关视图中长时间运行任务的进度的更新的主要内容,如果未能解决你的问题,请参考以下文章

带有进度通知的长时间运行的后台任务

长时间运行任务的 Grails 状态更新

iOS 在长时间运行任务后显示警报视图

播放框架运行长时间阻塞任务,而不阻塞客户端

3层模式下长时间调用的进度条提示方案

如何更新 UI 以显示 Core Data 长时间运行的进程?