带有Plotly/Dash回调和芹菜/Redis的Django应用
我有一个Django项目,我的一个应用程序使用DASH/PLOTLY提供交互式数据可视化,并将其部署到Heroku。随着我的数据库越来越大,收集相关数据,将其归一化和绘制所需的时间通常大于30秒,因此请求已计时,我的情节不再出现了,这很可悲,因为他们的工作很棒:/
我现在要做的是使用芹菜,以便将数据收集和归一化派遣到工人并不同步地将Redis作为经纪人,但是由于我不这样做,这变得非常困惑在这些框架上有任何经验,我找不到这样的应用程序的示例。 我要在下面发布一个简化且类似的应用程序,而没有任何芹菜物质,这些内容完全可以正常工作(用户提供了种子,并且应用程序绘制了一个散点图,该散点图与从该种子生成的随机数)。
项目树是:
djcel/
djcel/
worker/
dash_apps/
test_apps/
plot.py
templates/
worker/
scatter_plot.html
urls.py
views.py
主要文件是:
plot.py
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
from django_plotly_dash import DjangoDash
import plotly.graph_objects as go
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = DjangoDash('ScatterPlot', external_stylesheets=external_stylesheets)
def scatter_plot(seed):
"""
Plots random data.
"""
import numpy as np
np.random.seed(seed=seed)
x = np.arange(1,1000,1)
y = np.random.rand(1000)
fig = go.Figure(data=go.Scatter(x=x, y=y, mode='markers'))
return fig
seeds = [11, 42, 97, 1001]
app.layout = lambda: html.Div([
html.Div([
html.Div([
dcc.Dropdown(
id='seed',
options=[{'label': i, 'value': i} for i in seeds],
placeholder='Select the seed...'
)
],
style={'width': '30%', 'display': 'inline-block'})
]),
dcc.Graph(id='Scatter-plot'),
])
@app.callback(
Output('Scatter-plot', 'figure'),
Input('seed', 'value')
)
def update_graph(seed):
if(seed):
return scatter_plot(seed)
else:
return go.Figure()
views.py
from django.shortcuts import render
from plotly.offline import plot
from django.views.decorators.cache import cache_page
def scatter_plot_dispatch(requests):
return render(requests, 'worker/scatter_plot.html')
urls.py
from django.urls import path
from . import views
from .dash_apps.test_apps import plot
urlpatterns = [
path('scatterplot/', views.scatter_plot_dispatch, name="worker.scatter_plot"),
]
scatse_plot.html
{% extends "base.html" %}
{% block content %}
{% load plotly_dash %}
<br>
<div class="{% plotly_class name="ScatterPlot" %} card" style="height:100%; width:100%">
{% plotly_app name="ScatterPlot" ratio=0.85 %}
</div>
{% endblock %}
我想不同步运行scate_plot
,并在完成任务后使用结果图对象更新了我的视图。我知道如何通过芹菜/Redis发送任务以及如何检查其状态,但是由于Djangodash回调,我正在努力连接这些部件。如何使回调返回一条消息,警告用户可能需要一分钟的时间才能绘制图形,然后在完成任务完成后自动对其进行更新?有什么想法吗?我已经试图弄清楚了一段时间。我很高兴提供任何进一步的信息。谢谢!!
I have a Django project where one of my apps provides interactive data visualization using Dash/Plotly and is deployed to Heroku. As my database grew bigger, the time it takes to collect the relevant data, normalize it, and plot it, is now often larger than 30s, therefore the requests are timing out and my plots are not showing up anymore, which is sad, because they were working great :/
What I'm trying to do now is to use Celery so that the data collection and normalization is dispatched to a worker and run asynchronously having Redis as a broker, but this is getting extremely confusing as I don't have any experience with these frameworks and I couldn't find an example of such an application.
I'm posting below a simplified and analogous app without any Celery stuff, that works exactly how I want (the user provides a seed and the app plots a scatter plot with random numbers generated from that seed).
The project tree is:
djcel/
djcel/
worker/
dash_apps/
test_apps/
plot.py
templates/
worker/
scatter_plot.html
urls.py
views.py
And the main files are:
plot.py
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
from django_plotly_dash import DjangoDash
import plotly.graph_objects as go
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = DjangoDash('ScatterPlot', external_stylesheets=external_stylesheets)
def scatter_plot(seed):
"""
Plots random data.
"""
import numpy as np
np.random.seed(seed=seed)
x = np.arange(1,1000,1)
y = np.random.rand(1000)
fig = go.Figure(data=go.Scatter(x=x, y=y, mode='markers'))
return fig
seeds = [11, 42, 97, 1001]
app.layout = lambda: html.Div([
html.Div([
html.Div([
dcc.Dropdown(
id='seed',
options=[{'label': i, 'value': i} for i in seeds],
placeholder='Select the seed...'
)
],
style={'width': '30%', 'display': 'inline-block'})
]),
dcc.Graph(id='Scatter-plot'),
])
@app.callback(
Output('Scatter-plot', 'figure'),
Input('seed', 'value')
)
def update_graph(seed):
if(seed):
return scatter_plot(seed)
else:
return go.Figure()
views.py
from django.shortcuts import render
from plotly.offline import plot
from django.views.decorators.cache import cache_page
def scatter_plot_dispatch(requests):
return render(requests, 'worker/scatter_plot.html')
urls.py
from django.urls import path
from . import views
from .dash_apps.test_apps import plot
urlpatterns = [
path('scatterplot/', views.scatter_plot_dispatch, name="worker.scatter_plot"),
]
scatter_plot.html
{% extends "base.html" %}
{% block content %}
{% load plotly_dash %}
<br>
<div class="{% plotly_class name="ScatterPlot" %} card" style="height:100%; width:100%">
{% plotly_app name="ScatterPlot" ratio=0.85 %}
</div>
{% endblock %}
I would like to run scatter_plot
asynchronously and have my view updated with the resulting figure object when the task is done. I know how to send tasks via Celery/Redis and how to check on their status, but I'm struggling to connect the pieces because of the DjangoDash callback. How could I make the callback return a message right away warning the user that it could take up to a minute to have the graph plotted and then have it automatically updated when the task is complete? Any ideas? I've been trying to figure this out for quite a while now. I'm happy to provide any further information. Thanks!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论