如何在具有多个唯一图形的布局上实现 Dash/Plotly 清单持久性?
Posted
技术标签:
【中文标题】如何在具有多个唯一图形的布局上实现 Dash/Plotly 清单持久性?【英文标题】:How do I implement Dash/Plotly checklist persistence on a layout with multiple unique graphs? 【发布时间】:2021-11-25 18:45:10 【问题描述】:我的仪表板有一个 2 x 2 的图表布局,每个图表上覆盖一个清单。
每个图表都需要一个唯一的 ID,以便通过回调进行实时更新。 这些 ID 在循环中生成(例如,graph-BMW、graph-MB 等)。 同样,每个清单都有一个通过相同循环生成的唯一 ID(例如,清单-BMW、清单-MB 等)。 这些 ID 被传递到回调的 input 和 output。
计算图表数据并返回清单值和图形。
由于清单需要包含在与图表相同的 DIV 中,因此它们是嵌套的,然后在布局中解包。
所有这些都完美运行,除了一个例外:persistence
不起作用。
如果单击清单,刷新页面时我无法保留当前(新)状态。
清单值总是返回到未选中状态,因为它似乎被重置了。
我该如何解决这个问题?
应用程序的精简版:
cars = ['BMW', 'MB', 'AUDI', 'FIAT']
app3 = dash.Dash(__name__)
for car in cars:
graph = 'graph-' + car
checklist = 'checklist-' + car
@app3.callback(Output(checklist, 'value'),
Output(graph, 'figure'),
Input(checklist, 'value'),
Input('interval-component', 'n_intervals'))
def update_charts(checklist, n_interval, c=car):
data = get_car_data(c)
df = calcs_on_car_data(data)
fig = go.Figure(go.Scatter(x=df.index, y=df['A'].values))
return checklist, fig
list_graphs = []
for car in cars:
list_graphs.append([html.Div(className='box',
children=[html.Div([
dcc.Checklist(id='checklist-' + str(car),
options=['label': '', 'value': 'on'], value=[],
persistence=True),
dcc.Graph(id='graph-' + str(car))])
])
])
app3.layout = html.Div([
*[j for i in list_graphs for j in i], # unpacking a nested list
dcc.Interval(id='interval-component', interval=300000, n_intervals=0)
])
if __name__ == '__main__':
app3.run_server(debug=True)
【问题讨论】:
查看本期/PR github.com/plotly/dash/pull/903 感谢您的指点。您的看法是:在这一点上这是一个失败的原因吗? 我记得曾经遇到过同样的问题并用一些非常丑陋/hacky的解决方案解决了它。但那是大约 2 年前的事了。 您的代码似乎没有 get_car_data(c) 和 calcs_on_car_data(data) 函数。请提供示例数据,以便我可以提供帮助 为什么def update_charts
在(第一个)“for”循环中?这在Dash 中正常吗?
【参考方案1】:
您可以按照以下步骤操作
利用会话变量来存储清单值 一旦页面刷新完成(所有页面元素都重新加载),触发访问会话变量的调用并将值分配给相关清单。【讨论】:
【参考方案2】:循环回调似乎破坏了持久性功能。通过删除清单输出将其删除,持久性按预期工作。这是MWE,
import plotly.express as px
from dash import dash, dcc, html, Output, Input
def make_car_card(car: str):
graph_id = f'graph-car'
checklist_id = f'checklist-car'
card = html.Div(className='box',
children=html.Div([
dcc.Checklist(id=checklist_id,
options=['label': '', 'value': 'on'], value=[],
persistence=True),
dcc.Graph(id=graph_id)])
)
@app.callback(Output(graph_id, 'figure'), Input('interval-component', 'n_intervals'), Input(checklist_id, 'value'))
def update_charts(_, value, this_car=car):
if 'on' not in value:
return px.scatter()
return px.scatter(px.data.iris(), x="sepal_width", y="sepal_length", title=this_car)
return card
# Create small example app.
app = dash.Dash(__name__)
app.layout = html.Div(
[make_car_card(car) for car in ['BMW', 'MB', 'AUDI', 'FIAT']] +
[dcc.Interval(id='interval-component', interval=300000, n_intervals=0)]
)
if __name__ == '__main__':
app.run_server(debug=True)
【讨论】:
以上是关于如何在具有多个唯一图形的布局上实现 Dash/Plotly 清单持久性?的主要内容,如果未能解决你的问题,请参考以下文章
如何在屏幕上实现具有许多文本字段的 NSScrollView?