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

Python3.6.3+Django2.0.3:如何在模板中嵌入StreamingHttpResponse实时展示任务输出?

实现实时展示耗时任务输出的方案

嘿,作为Django新手遇到这种实时输出的需求确实有点绕,不过咱们可以用SSE(Server-Sent Events)+ 后台线程的方案来实现,刚好适配你的Django 2.0.3版本,不需要太复杂的第三方库。下面一步步来:

1. 改造独立Python脚本

首先得让你的耗时脚本把输出写到一个能被Django实时读取的地方,比如临时文件。修改你的脚本,让它把内容输出到指定文件(行缓冲模式保证实时写入):

# long_task.py(你的独立脚本)
import time

def run_task(output_file_path):
    # buffering=1 开启行缓冲,确保print内容实时写入文件
    with open(output_file_path, 'w', buffering=1) as f:
        for i in range(10):
            progress_msg = f"任务进度:{i*10}%"
            print(progress_msg)
            f.write(f"{progress_msg}\n")
            time.sleep(1)
        f.write("任务执行完成!\n")

if __name__ == "__main__":
    import sys
    if len(sys.argv) > 1:
        run_task(sys.argv[1])

2. Django视图实现

需要两个视图:一个用来触发任务(启动后台线程跑脚本),另一个用来通过SSE推送实时输出。在你的app的views.py中添加:

import os
import tempfile
import threading
import subprocess
from django.http import HttpResponse, HttpResponseBadRequest
from django.shortcuts import render

# 触发耗时任务的视图
def trigger_task(request):
    if request.method == 'POST':
        # 为当前用户创建唯一临时文件
        temp_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
        temp_file.close()
        # 将临时文件路径存入session,关联用户与任务输出
        request.session['task_output_file'] = temp_file.name

        # 用后台线程启动脚本,避免阻塞主请求
        def run_script():
            # 替换成你的脚本实际路径
            subprocess.run(['python', './long_task.py', temp_file.name])
            # 任务完成后可选择删除临时文件,避免磁盘占用
            # os.unlink(temp_file.name)

        # 启动守护线程,Django进程结束时线程自动退出
        threading.Thread(target=run_script, daemon=True).start()

        # 跳转到进度展示页面
        return render(request, 'task_progress.html')
    return HttpResponseBadRequest("仅接受POST请求")

# SSE实时推送视图
def task_stream(request):
    output_file = request.session.get('task_output_file')
    if not output_file or not os.path.exists(output_file):
        return HttpResponse("无运行中任务或文件不存在", status=404)

    # 设置SSE响应头
    response = HttpResponse(content_type='text/event-stream')
    response['Cache-Control'] = 'no-cache'
    response['Connection'] = 'keep-alive'

    # 实时读取文件内容并推送
    def stream_content():
        with open(output_file, 'r') as f:
            # 先推送已有的内容
            existing_content = f.read()
            if existing_content:
                # 替换换行符为<br>适配HTML展示
                yield f"data: {existing_content.replace('\n', '<br>')}\n\n"
            # 监听文件新增内容
            while True:
                new_line = f.readline()
                if new_line:
                    yield f"data: {new_line.strip().replace('\n', '<br>')}\n\n"
                # 检测任务完成,终止流
                if "任务执行完成!" in new_line:
                    break

    return HttpResponse(stream_content(), content_type='text/event-stream')

3. 模板修改(适配你的{{ stream }}位置)

修改你的进度展示模板(比如命名为task_progress.html),添加SSE前端代码来接收并更新输出:

{% load pagePieces %}
{% page_header %}
<div class="container">
  <div class="row">
    <!-- 原模板内容保留,替换{{ stream }}为带ID的容器 -->
    <div id="stream">任务启动中...</div>
  </div>
</div>

<script>
// 初始化SSE连接,拉取实时输出
const eventSource = new EventSource("{% url 'task_stream' %}");

// 接收服务器推送的内容并更新页面
eventSource.onmessage = function(event) {
  const streamDiv = document.getElementById('stream');
  streamDiv.innerHTML = event.data;
};

// 处理连接错误或任务完成
eventSource.onerror = function(error) {
  console.error('SSE连接出错:', error);
  eventSource.close();
  const streamDiv = document.getElementById('stream');
  streamDiv.innerHTML += "<br>连接已关闭或任务完成。";
};
</script>

4. 配置路由

在项目的urls.py中添加视图路由:

from django.urls import path
from your_app_name import views  # 替换为你的app名称

urlpatterns = [
    # 其他路由...
    path('trigger-task/', views.trigger_task, name='trigger_task'),
    path('task-stream/', views.task_stream, name='task_stream'),
]

注意事项

  • 临时文件管理:任务完成后可以手动删除临时文件,或者添加定时清理逻辑,避免磁盘占用。
  • 线程安全性:如果是多用户场景,用session关联用户和临时文件能避免输出混淆。
  • 兼容性:SSE支持大部分现代浏览器,若需兼容IE可考虑用WebSocket替代,但复杂度会更高。
  • 脚本路径:subprocess.run中的脚本路径要写对,建议用绝对路径避免问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:11:21