You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中更新Celery任务的状态?

Django中Celery任务状态更新实现方案

需求概述

需要在Django项目中实现多文本文件上传后,Celery处理任务的状态实时更新,并在前端表格中展示对应文件的任务状态。

步骤实现

1. 修正并完善Celery任务代码(tasks.py)

原任务未接收文件参数,调整为接收文件ID,同时支持任务状态追踪:

from celery import shared_task
from .models import File

@shared_task(bind=True)
def text_analysis(self, file_id):
    # 获取目标文件对象
    file_obj = File.objects.get(id=file_id)
    try:
        # 更新任务为处理中状态
        self.update_state(state='PROGRESS', meta={'status': '正在提取文件数字...'})
        
        # 执行文本分析核心逻辑(示例)
        with file_obj.file.open() as f:
            content = f.read().decode('utf-8')
            numbers = [int(s) for s in content.split() if s.isdigit()]
            result = {'提取到的数字': numbers, '数量': len(numbers)}
        
        # 更新文件记录状态与结果
        file_obj.status = 'SUCCESS'
        file_obj.result = str(result)
        file_obj.save()
        return result
    except Exception as e:
        # 处理失败时更新状态
        file_obj.status = 'FAILURE'
        file_obj.save()
        self.update_state(state='FAILURE', meta={'error': str(e)})
        raise

2. 修改视图中的文件上传处理函数

为每个上传文件创建数据库记录,关联Celery任务ID:

from django.shortcuts import render
from .models import File
from .tasks import text_analysis

def text_analysis_view(request):
    if request.method == 'POST':
        text_files = request.FILES.getlist("files")
        for text_file in text_files:
            # 创建文件记录,初始状态为待处理
            file_obj = File.objects.create(
                user=request.user,
                file=text_file,
                status='PENDING'
            )
            # 启动Celery任务并保存任务ID
            task = text_analysis.delay(file_obj.id)
            file_obj.task_id = task.id
            file_obj.save()
    # 获取当前用户的所有文件记录
    files = File.objects.filter(user=request.user).order_by('-created_at')
    return render(request, "demo_demo.html", {"files": files})

3. 调整数据库模型(models.py)

添加task_id和status字段,关联任务与记录状态:

from django.db import models
from django.contrib.auth.models import User

class File(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    file = models.FileField(upload_to='text_files/')
    created_at = models.DateTimeField(auto_now_add=True)
    task_id = models.CharField(max_length=255, blank=True, null=True)
    # 状态选项:*PENDING*(待处理)、*PROGRESS*(处理中)、*SUCCESS*(完成)、*FAILURE*(失败)
    status = models.CharField(max_length=20, default='PENDING')
    result = models.TextField(blank=True, null=True)

4. 更新HTML模板展示状态

修改模板显示文件信息,并添加前端轮询逻辑实时更新状态:

<main>
<form method="POST" enctype="multipart/form-data" id="texts_form">
{% csrf_token %}            
<input name="files" type="file" multiple>
<button type="submit">提交</button>
</form>                 
<div class="table-data">
<div class="order">     
<div class="head">
<h3>最近上传的文本文件</h3>
</div>                                      
<table>
<thead>
<tr>
<th>文件名</th>                               
<th>创建时间</th>
<th>状态</th>
</tr>
</thead>                        
<tbody>
{% for file in files %}
<tr data-task-id="{{ file.task_id }}" data-file-id="{{ file.id }}">            
<td>{{ file.file.name }}</td>                                                                           
<td>{{ file.created_at|date:"Y-m-d H:i:s" }}</td>
<td class="status-cell">{{ file.status }}</td>                           
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</main>

<script>
// 轮询更新任务状态
function updateTaskStatuses() {
    const rows = document.querySelectorAll('tr[data-task-id]');
    rows.forEach(row => {
        const taskId = row.getAttribute('data-task-id');
        const statusCell = row.querySelector('.status-cell');
        if (taskId && statusCell.textContent !== 'SUCCESS' && statusCell.textContent !== 'FAILURE') {
            fetch(`/task-status/${taskId}/`)
                .then(response => response.json())
                .then(data => {
                    statusCell.textContent = data.status;
                    // 处理中状态显示详细进度
                    if (data.status === 'PROGRESS') {
                        statusCell.textContent += `: ${data.meta.status}`;
                    }
                })
                .catch(error => console.error('更新状态失败:', error));
        }
    });
}

// 每3秒执行一次状态更新
setInterval(updateTaskStatuses, 3000);
</script>

5. 添加任务状态查询API视图

在views.py中新增查询任务状态的接口:

from django.http import JsonResponse
from celery.result import AsyncResult

def task_status(request, task_id):
    task_result = AsyncResult(task_id)
    if task_result.state == 'PENDING':
        response = {
            'status': task_result.state,
            'meta': '任务等待中...'
        }
    elif task_result.state == 'PROGRESS':
        response = {
            'status': task_result.state,
            'meta': task_result.info.get('status', '处理中...')
        }
    elif task_result.state == 'SUCCESS':
        response = {
            'status': task_result.state,
            'meta': '任务完成'
        }
    else:
        # 处理失败或其他异常状态
        response = {
            'status': task_result.state,
            'meta': task_result.info.get('error', '任务失败')
        }
    return JsonResponse(response)

6. 配置URL路由

在urls.py中添加状态查询路由:

from django.urls import path
from . import views

urlpatterns = [
    path('text-analysis/', views.text_analysis_view, name='text_analysis'),
    path('task-status/<str:task_id>/', views.task_status, name='task_status'),
]

已尝试但未解决的方案

  • 基于Django的Celery结果后端方案
  • FastAPI+Celery的前端状态更新方案

内容的提问来源于stack exchange,提问作者Joker King

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 05:17:49