首页 > 解决方案 > 回调的输出作为另一个回调的输入,第二个回调运行两次

问题描述

仪表板包括一个下拉列表、一个表格和一个图表。通过从下拉列表中选择一个项目,可以显示表格的一些行,并用图形绘制表格中的数据。我有两个回调,

at the first one:
input : dropdown
output: table
second one:
input: table
output: figure

所以第一个回调的输出是第二个回调的输入。

以下代码输出如下所示: 在此处输入图像描述

import dash
import dash_table
import pandas as pd
from copy import deepcopy
import plotly.graph_objects as go
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output


data = pd.DataFrame({"a": ["a1", "a2"],
                     "b": [1, 2]})

app = dash.Dash(
    __name__,
    external_stylesheets=[dbc.themes.BOOTSTRAP],
    prevent_initial_callbacks=True,
)

app.layout = dbc.Container(
    [
        dbc.Row(dbc.Col([dcc.Dropdown(
            id='dropdown1',
            options=[
                {'label': '1', 'value': 1},
                {'label': '2', 'value': 2}
            ],
            value=1)])),
        dbc.Row(
            dbc.Col([
                dash_table.DataTable(
                    id="datatable",
                    columns=[dict(id=i,
                                  name=j,
                                  )
                             for i, j in zip(
                        ["a", "b"],
                        ["a", "b"],
                    )],
                    data=data.loc[data['a'] ==
                                  "a1"].to_dict("records"),
                    sort_mode="single",
                )
            ])),
        dbc.Row([dbc.Col([html.Div(
            children=dcc.Graph(id="graph"), className="card")
        ])]),
    ], fluid=True,
)
########################################################


@app.callback(
    Output("datatable", "data"),
    [Input("dropdown1", "value")],
    prevent_initial_call=True
)
def update_current_table(value):

    idx = int(value)
    print(idx)

    if idx == 1:
        df = (data.loc[data["a"] == "a1"])
        return df.to_dict("records")
    else:
        df = deepcopy(data.loc[data["a"] == "a2"])
        return df.to_dict("records")
########################################################


@ app.callback(
    Output('graph', 'figure'),
    [Input("datatable", "derived_virtual_data"),
     Input("dropdown1", "value")
     ],
    prevent_initial_call=True
)
def update_figure(table, value):

    df = pd.DataFrame(table)
    print(df)

    fig = go.Figure()
    return fig


if __name__ == "__main__":
    app.run_server(debug=True, port=8000)

这里的问题是回调运行两次:

    a  b
0  a1  1
    a  b
0  a2  2

并且第一次打印表的先前值这会导致我正在处理的主要代码中出现错误。

如何防止破折号两次运行回调?

我发现一些其他问题抱怨运行回调两次,但我找不到合适的解决方案。

标签: plotly-dash

解决方案


问题是您有两个输入用于运行两次的回调:

@ app.callback(
    Output('graph', 'figure'),
    [Input("datatable", "derived_virtual_data"),
     Input("dropdown1", "value")
     ],
    prevent_initial_call=True
)
def update_figure(table, value):

下拉列表更改,并触发此回调,但它也触发表更新。更新后的表会导致derived_virtual_data再次触发此回调。您可以通过将下拉值State改为 a 来解决此问题,如下所示:

@ app.callback(
    Output('graph', 'figure'),
    [Input("datatable", "derived_virtual_data")],
    [State("dropdown1", "value"),]
    prevent_initial_call=True
)
def update_figure(table, value):

编辑:在另一次通读中,您甚至不使用value第二个输入中的下拉列表。完全删除它也可以:

@ app.callback(
    Output('graph', 'figure'),
    [Input("datatable", "derived_virtual_data")],
    prevent_initial_call=True
)
def update_figure(table):

推荐阅读