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

django-plotly-dash中实现长任务进度条可行吗?附示例求方案

在django-plotly-dash中实现长任务进度条的方案

一、原生Dash Background Callback方案(可行)

你提供的Dash进度条代码可以适配到django-plotly-dash中,核心是用DjangoDash替代原生dash.Dash初始化应用,并调整任务管理器的配置以适配Django环境。

适配步骤:

  1. 配置后台任务管理器
    保持Diskcache/Celery的配置逻辑,但注意路径和Celery的Django适配:

    import os
    import diskcache
    from celery import Celery
    from dash import DiskcacheManager, CeleryManager
    
    if 'REDIS_URL' in os.environ:
        # 复用Django的Celery配置,避免单独初始化的兼容性问题
        celery_app = Celery('your_django_project', broker=os.environ['REDIS_URL'], backend=os.environ['REDIS_URL'])
        background_callback_manager = CeleryManager(celery_app)
    else:
        # 缓存路径设置为Django项目可访问目录,确保权限
        cache = diskcache.Cache("./django_dash_cache")
        background_callback_manager = DiskcacheManager(cache)
    
  2. 用DjangoDash注册应用
    替换原生dash.Dash为django_plotly_dash.DjangoDash:

    from django_plotly_dash import DjangoDash
    from dash import Input, Output, html
    import time
    
    app = DjangoDash("ProgressBarApp", background_callback_manager=background_callback_manager)
    
    # 原有的layout和callback代码完全复用
    app.layout = html.Div(
        [
            html.Div([
                html.P(id="paragraph_id", children=["Button not clicked"]),
                html.Progress(id="progress_bar", value="0"),
            ]),
            html.Button(id="button_id", children="Run Job!"),
            html.Button(id="cancel_button_id", children="Cancel Running Job!"),
        ]
    )
    
    @app.callback(
        output=Output("paragraph_id", "children"),
        inputs=Input("button_id", "n_clicks"),
        background=True,
        running=[
            (Output("button_id", "disabled"), True, False),
            (Output("cancel_button_id", "disabled"), False, True),
            (Output("paragraph_id", "style"), {"visibility": "hidden"}, {"visibility": "visible"}),
            (Output("progress_bar", "style"), {"visibility": "visible"}, {"visibility": "hidden"}),
        ],
        cancel=Input("cancel_button_id", "n_clicks"),
        progress=[Output("progress_bar", "value"), Output("progress_bar", "max")],
        prevent_initial_call=True
    )
    def update_progress(set_progress, n_clicks):
        total = 5
        for i in range(total + 1):
            set_progress((str(i), str(total)))
            time.sleep(1)
        return f"Clicked {n_clicks} times"
    
  3. 在Django中集成应用

    • 方式一:通过URL直接访问
      在urls.py中添加:
      from django.urls import path
      from django_plotly_dash.views import add_to_session
      from .dash_apps import progress_app
      
      urlpatterns = [
          path('dash/progress/', add_to_session(progress_app.app), name='progress_dash'),
      ]
      
    • 方式二:嵌入到Django模板
      在模板中使用模板标签:
      {% load plotly_dash %}
      {% plotly_app name="ProgressBarApp" %}
      

注意事项:

  • 执行python manage.py collectstatic以加载Dash的静态资源。
  • Celery worker需配置DJANGO_SETTINGS_MODULE环境变量,确保和Django共用配置。
  • Diskcache目录需保证Django进程和后台任务进程都有读写权限。

二、替代方案(原生Dash方案兼容问题时使用)

如果遇到django-plotly-dash版本对Background Callback支持不完善的情况,可采用Django+Celery+前端轮询/WebSocket的方案。

方案1:Celery+前端轮询

  1. 创建进度存储模型

    from django.db import models
    
    class TaskProgress(models.Model):
        task_id = models.CharField(max_length=255, unique=True)
        progress = models.IntegerField(default=0)
        total = models.IntegerField(default=100)
        status = models.CharField(max_length=20, choices=[('running', 'Running'), ('completed', 'Completed'), ('cancelled', 'Cancelled')], default='running')
    
  2. 编写Celery任务

    from celery import shared_task
    from .models import TaskProgress
    import time
    
    @shared_task(bind=True)
    def long_running_task(self, task_id):
        progress_obj = TaskProgress.objects.get(task_id=task_id)
        total = 5
        for i in range(total + 1):
            if not self.request.is_aborted():
                progress_obj.progress = i
                progress_obj.total = total
                progress_obj.save()
                time.sleep(1)
            else:
                progress_obj.status = 'cancelled'
                progress_obj.save()
                return
        progress_obj.status = 'completed'
        progress_obj.save()
    
  3. Django视图处理任务交互
    编写启动、取消、查询进度的API视图,前端通过AJAX轮询获取进度并更新进度条(可参考常规Django API+JS轮询实现)。

方案2:Django Channels+WebSocket实时更新

通过WebSocket实现进度的实时推送,无需前端轮询,适合高实时性需求。需配置Django Channels通道层,Celery任务执行时通过Channels发送进度消息到前端页面。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 09:40:02