我有一个 Celery 任务,需要在几分钟内填充 PostgreSQL 数据库。我想在 Django 视图中从数据库中检索当前数据并将其发送到模板,该模板将根据任务的进度不断重新显示。所以,我想实时更新模板。
目前,我有一个调用 Celery 任务并获取任务结果的视图。然后它渲染模板并以字符串形式向其发送任务结果以及任务 id。
我对 AJAX 不太熟悉,但根据我所读到的内容,我需要 AJAX 调用的另一个视图来检索任务的最新结果。
这是到目前为止的代码:
渲染模板的视图:
def dashboard(request):
result = prepare_database.delay()
return render(request, 'appname/template.html',
{'task_id': result.task_id})
获取当前数据的视图
def current_data(request):
task_id = request.GET.get('task_id')
if task_id:
async_result = AsyncResult(task_id)
return JsonResponse({'data': async_result.get()})
Ajax 轮询任务(同样,对于 AJAX 来说非常陌生):
function pollTaskStatus(taskId) {
$.ajax({
url: '/current_data/',
method: 'GET',
data: {
task_id: taskId
},
success: function(response) {
if (response.status === 'in_progress') {
} else {
// Update the HTML with the results
}
},
error: function(xhr, status, error) {
}
});
}
$(document).ready(function() {
var taskId = '{{ task_id }}'; // Get the task ID from the template
pollTaskStatus(taskId);
});
如果我的整个方法有缺陷,请告诉我,因为我不太确定这是正确的方法。目前一切设置是否正确?另外,如果还有什么需要我澄清或详细说明的,请告诉我。
您可以通过在ajax响应中提供
status
键来修改您的视图,以基于此设置条件。像下面这样:
def current_data(request):
task_id = request.GET.get('task_id')
if task_id:
async_result = AsyncResult(task_id)
if async_result.state == 'PROGRESS':
response_data = {
'status': 'in_progress',
'data': 'Your code ton get data'
}
elif async_result.state == 'SUCCESS':
response_data = {
'status': 'completed',
'data': 'Your code ton get data'
}
else:
# manage any other status if reruired
return JsonResponse(response_data)
return JsonResponse({'status': 'no_task'})
还可以通过设置
setTimeout()
方法在几毫秒后调用函数,通过设置定期轮询任务状态并使用最新进度数据更新模板。您可以执行如下操作:
function pollTaskStatus(taskId) {
$.ajax({
url: '/current_data/',
method: 'GET',
data: { task_id: taskId },
success: function(response) {
if (response.status === 'in_progress') {
// Update the HTML with the progress data
setTimeout(function() {
pollTaskStatus(taskId);
}, 1000); // Poll every 1 second
} else if (response.status === 'completed') {
// Update the HTML with the final results
}
},
error: function(xhr, status, error) {
console.error('Error polling task status:', error);
}
});
}