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

Django使用Redis-Queue执行后台任务后如何将结果回传前端展示下载按钮

实现方案

整体逻辑

  • 任务提交入队后将RQ生成的job_id返回给前端页面
  • 前端携带job_id定时轮询后端的任务状态查询接口
  • 后端根据job_id从RQ中查询任务状态,任务完成则返回生成的文件名,失败返回错误信息
  • 前端根据返回结果动态渲染下载按钮或错误提示

1. 调整视图文件views.py

新增任务状态查询接口,同时修改原提交逻辑传递job_id到模板:

from django.shortcuts import render
from django.contrib import messages
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse, JsonResponse
from rq.job import Job
from redis import Redis
from .forms import ScriptParamForm
from .queue_job import my_job

# 和你启动RQ worker的Redis配置保持一致
redis_conn = Redis(host='localhost', port=6379, db=0)

@csrf_exempt
def home(request):
    context = {}
    if request.method == 'POST':
        if request.POST.get("btn_submit"):
            req_dict = dict(request.POST)         
            form     = ScriptParamForm(request.POST)
            context['form'] = form
            if form.is_valid():
                req_dict = dict(request.POST)
                # 确保my_job是RQ入队操作,返回Job实例
                job = my_job(outdir=tmp_dir, **req_dict)
                context['job_id'] = job.id
            return render(request, 'webapp/home.html', context)

        elif request.POST.get("btn_download"):
            serve_file = request.POST.get("btn_download")
            with open(serve_file, 'rb') as fp:
                response = HttpResponse(fp, headers={
                    'Content-Type': 'application/zip',
                    'Content-Disposition': f'attachment; filename="{serve_file}"'
                })
                return response
    else:
        form = ScriptParamForm()
        context['form'] = form
        return render(request, 'webapp/home.html', context)

# 新增任务状态查询接口
@csrf_exempt
def check_job_status(request):
    if request.method == 'POST':
        job_id = request.POST.get('job_id')
        try:
            job = Job.fetch(job_id, connection=redis_conn)
        except:
            return JsonResponse({'status': 'invalid', 'msg': '任务ID不存在'})
        if job.is_finished:
            # job.result为my_job执行完成后return的文件路径
            return JsonResponse({'status': 'finished', 'serve_file': job.result})
        elif job.is_failed:
            return JsonResponse({'status': 'failed', 'msg': '任务执行失败,请重试'})
        else:
            return JsonResponse({'status': 'running'})
    return JsonResponse({'status': 'error'})

同步添加路由到urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
    path('check-job-status/', views.check_job_status, name='check_job_status'),
]

2. 修改模板文件home.html

新增job_id存储字段,调整下载按钮默认隐藏:

{% extends 'base.html' %}
{% block content %}
<form method="POST" autocomplete="on">
    {% csrf_token %}
     
    <!-- 表单字段区域 -->
    ...

    <!-- 新增隐藏域存储job_id -->
    <input type="hidden" id="job-id" value="{{ job_id|default:'' }}">

    <!-- 按钮区域 -->
    <div>
        <button type="submit" name="btn_submit" value="submit" class="btn btn-primary" id="btn-submit">Submit</button>

        <!-- 下载按钮默认隐藏,任务完成后JS控制显示 -->
        <button type="submit" name="btn_download" id="download-btn" value="" class="btn btn-primary d-none">Download</button>
        
        <span class="not-visible" id="calc-msg"> This may take a few, relax! :) </span>
        <span id="error-msg" class="text-danger d-none"></span>
    </div>
</form>
{% endblock content %}

3. 修改JS文件main.js

添加轮询逻辑,动态更新页面状态:

var x = document.getElementById("btn-submit")
var jobId = document.getElementById("job-id").value
var pollTimer = null

x.onclick = function () {
    $("#calc-msg").removeClass("not-visible");
    setInterval(function(){blink()}, 1000);
    // 提交任务后启动轮询,每3秒查询一次状态
    if(jobId) {
        pollTimer = setInterval(checkJobStatus, 3000)
    }
};

function blink() {
    $("#calc-msg").fadeTo(100, 0.1).fadeTo(200, 1.0);
}

function checkJobStatus() {
    $.post('/check-job-status/', {
        'job_id': jobId,
        'csrfmiddlewaretoken': $('input[name="csrfmiddlewaretoken"]').val()
    }, function(res) {
        if(res.status === 'finished') {
            // 任务完成,停止轮询,显示下载按钮
            clearInterval(pollTimer)
            $("#calc-msg").addClass("not-visible");
            $("#download-btn").val(res.serve_file).removeClass("d-none")
        } else if(res.status === 'failed' || res.status === 'invalid') {
            // 任务失败,停止轮询,显示错误信息
            clearInterval(pollTimer)
            $("#calc-msg").addClass("not-visible");
            $("#error-msg").text(res.msg).removeClass("d-none")
        }
    })
}

注意:你的my_job任务函数执行完成后需要返回生成的压缩文件的完整路径,才能在job.result中拿到对应文件名用于下载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 14:54:00