首页 > 解决方案 > 回调警告:回调错误创建破折号数据表

问题描述

我正在尝试从回调中生成一个表,虽然该表实际上正在生成,但我收到了一个警告:

更新 priceTable.data、priceTable.columns 的回调错误

dash.exceptions.InvalidCallbackReturnValue:回调 ..priceTable.data...priceTable.columns.. 是一个多输出。期望输出类型是列表或元组,但得到:无。

我知道我的问题在于我如何布置回调,但我不确定正确的格式应该是什么。我在网上找到了这个答案,这很有帮助,因为我在它之前有'return dt.DataTable(data = data, columns=columns)'。

代码布局:

import dash
import dash_html_components as html
import dash_core_components as dcc
import dash_table as dt
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
import pandas as pd

df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')

app = dash.Dash(__name__)

states = df.State.unique().tolist()
numSP = df['Number of Solar Plants'].unique().tolist()

app.layout = html.Div([
    dcc.Dropdown(
            id='filter_dropdown',
            options=[{'label':st, 'value':st} for st in states],
            value = states[0]
            ),
    html.Br(),
    dcc.Dropdown(
            id='filter2',
            options=[{'label':np, 'value':np} for np in numSP]
            #value = numSP[0]
            ),
    html.Br(),
    html.Button('Submit', id='submit-button-state', n_clicks=0),
    html.Br(),
    html.Div(id='output'),
    html.Div(
        #id ='priceTable'
        dt.DataTable(id='priceTable')
        )
])

回调部分代码:

@app.callback(
    [Output('priceTable', 'data'),Output('priceTable', 'columns')],
    [Input('submit-button-state', 'n_clicks')],
    [State('filter_dropdown', 'value')],
    [State('filter2', 'value')],
    [State('submit-button-state', 'n_clicks')],
)
def update_table(n_clicks, filter_dropdown, filter2, table):
    if n_clicks:
        if filter_dropdown is None and filter2 is None:
            raise PreventUpdate
        if filter_dropdown is not None and filter2 is not None:
            table = df[df.State == filter_dropdown]
            table = table[table['Number of Solar Plants'] == filter2]
        if filter_dropdown is None and filter2 is not None:
            table = df[df['Number of Solar Plants'] == filter2]
        if filter_dropdown is not None and filter2 is None:
            table = df[df.State == filter_dropdown]
        columns = [{"name": i, "id": i,} for i in (table.columns)]    
        data = table.to_dict('records')
        return data, columns

我尝试过的事情:

priceTable = (data, columns)
return priceTable 

谢谢!

标签: pythonpandascallbackplotly-dash

解决方案


它不起作用的原因是因为您没有在回调中处理未单击按钮的情况。即使尚未单击该按钮,您的回调仍需要返回一个元组(您的dataand columns)。

这就是错误在这里所说的:

期望输出类型是列表或元组,但得到:无。

Nonen_clicks0( ) 时,您不会返回任何 ( false)。

所以你需要做的是返回dataand columnswhen n_clicksis 0n_clicks与您所拥有的方法的唯一区别是,如果is ,您不会对数据应用任何过滤器0

完整示例:

import dash
import dash_html_components as html
import dash_core_components as dcc
import dash_table as dt
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
import pandas as pd

df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/solar.csv")

app = dash.Dash(__name__)

states = df.State.unique().tolist()
numSP = df["Number of Solar Plants"].unique().tolist()

app.layout = html.Div(
    [
        dcc.Dropdown(
            id="filter_dropdown",
            options=[{"label": st, "value": st} for st in states],
            value=states[0],
        ),
        html.Br(),
        dcc.Dropdown(
            id="filter2",
            options=[{"label": np, "value": np} for np in numSP]
            # value = numSP[0]
        ),
        html.Br(),
        html.Button("Submit", id="submit-button-state", n_clicks=0),
        html.Br(),
        html.Div(id="output"),
        html.Div(
            # id ='priceTable'
            dt.DataTable(id="priceTable")
        ),
    ]
)


def get_table_data(data):
    columns = [
        {
            "name": i,
            "id": i,
        }
        for i in (data.columns)
    ]
    data = data.to_dict("records")
    return (data, columns)


@app.callback(
    [Output("priceTable", "data"), Output("priceTable", "columns")],
    [Input("submit-button-state", "n_clicks")],
    [State("filter_dropdown", "value")],
    [State("filter2", "value")],
    [State("submit-button-state", "n_clicks")],
)
def update_table(n_clicks, filter_dropdown, filter2, table):
    if n_clicks:
        if filter_dropdown is None and filter2 is None:
            raise PreventUpdate
        if filter_dropdown is not None and filter2 is not None:
            table = df[df.State == filter_dropdown]
            table = table[table["Number of Solar Plants"] == filter2]
        if filter_dropdown is None and filter2 is not None:
            table = df[df["Number of Solar Plants"] == filter2]
        if filter_dropdown is not None and filter2 is None:
            table = df[df.State == filter_dropdown]

        (data, columns) = get_table_data(table)
        print("columns", columns)
        print("data", columns)

        return data, columns

    return get_table_data(df)


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

在上面的示例中,我还将用于从数据帧中检索数据和列的代码放在它自己的函数get_table_data中。为了确保始终返回您的数据元组,我使用了一个保护子句


推荐阅读