如何在具有多个唯一图形的布局上实施 Dash/Plotly 清单持久性?
How do I implement Dash/Plotly checklist persistence on a layout with multiple unique graphs?
我的仪表板有一个 2 x 2 的图表布局,每个图表上都有一个清单。
每个图表都需要一个唯一的 ID,通过回调 live-updated。
这些 ID 在循环中生成(例如 graph-BMW、graph-MB 等)。
同样,每个清单都有一个通过相同循环生成的唯一 ID(例如,checklist-BMW、checklist-MB 等)。
这些 ID 被传递给回调的 input 和 output。
计算图表数据并返回核对表值和图表。
由于清单需要包含在与图表相同的DIV中,因此它们被嵌套,然后在布局中解包。
所有这些都完美无缺,只有一个例外:persistence
不起作用。
如果单击清单,我无法在刷新页面时保留当前(新)状态。
清单值总是 returns 未选中,因为它似乎已重置。
我该如何解决这个问题?
应用程序的 stripped-down 版本:
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)
您可以按照以下步骤操作
- 利用会话变量存储清单值
- 一旦页面刷新完成(所有页面元素都重新加载),触发调用访问会话变量并为相关清单赋值。
循环回调似乎破坏了持久化功能。通过删除清单输出来删除它,持久性按预期工作。这是一个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)
我的仪表板有一个 2 x 2 的图表布局,每个图表上都有一个清单。
每个图表都需要一个唯一的 ID,通过回调 live-updated。 这些 ID 在循环中生成(例如 graph-BMW、graph-MB 等)。 同样,每个清单都有一个通过相同循环生成的唯一 ID(例如,checklist-BMW、checklist-MB 等)。 这些 ID 被传递给回调的 input 和 output。
计算图表数据并返回核对表值和图表。
由于清单需要包含在与图表相同的DIV中,因此它们被嵌套,然后在布局中解包。
所有这些都完美无缺,只有一个例外:persistence
不起作用。
如果单击清单,我无法在刷新页面时保留当前(新)状态。
清单值总是 returns 未选中,因为它似乎已重置。
我该如何解决这个问题?
应用程序的 stripped-down 版本:
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)
您可以按照以下步骤操作
- 利用会话变量存储清单值
- 一旦页面刷新完成(所有页面元素都重新加载),触发调用访问会话变量并为相关清单赋值。
循环回调似乎破坏了持久化功能。通过删除清单输出来删除它,持久性按预期工作。这是一个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)