You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dash如何通过双Dropdown配置回调更新查询数据并解决KeyError报错

错误原因

  • 回调输入参数顺序和装饰器中Input的顺序不匹配:装饰器里先声明的是event-dropdown的value,后声明的是run-dropdown的value,回调函数的参数要和这个顺序完全对应,你现在写反了,会导致取值错误。
  • 输出数量不匹配:你只声明了1个Output(output1的children属性),但函数最后返回了6个值,返回值数量和声明的Output数量不一致,就是触发KeyError: 'outputs_list'的直接原因。
  • 不推荐使用全局变量存储回调生成的数据:Dash是多线程多用户运行的,全局变量会被不同用户的操作覆盖,导致数据错乱。如果需要在多个回调间共享查询结果,建议用dcc.Store组件存储序列化后的中间数据。

正确的回调写法

如果你需要把下拉框的值用于数据查询,同时把查询结果用于更新图表、显示文本,推荐修改方案如下:

  1. 先在layout中添加dcc.Store组件,用来存储查询得到的中间数据
  2. 回调的Output数量和返回值数量保持完全一致
  3. 回调参数顺序和Input的顺序一一对应

修改后的完整代码示例

import dash
from dash import dcc, html, Input, Output, State

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Dropdown(
        id='event-dropdown',
        options=[
            {'label': '2021 test', 'value': '12345'},
            {'label': '2021 test 2', 'value': '78901'},
        ],
        value = '12345', # 注意初始值要在options的value列表里,不然会取空
        searchable=False,
        style={"width": "40%", "padding-left": "75px", "padding-top": "5px","padding-bottom": "5px","text-align": "center"}
    ),
    dcc.Dropdown(
        id='run-dropdown',
        options=[
            {'label': 'Practice 1', 'value': 'Practice 1'},
            {'label': 'Practice 2', 'value': 'Practice 2'},
        ],
        value = 'Practice 1',
        searchable=False,
        style={"width": "40%", "padding-left": "75px", "padding-top": "5px","padding-bottom": "5px","text-align": "center"}
    ),
    dcc.Graph(id='lapTime-graph',style={'width': '100%', 'height': '900px'}),
    dcc.Interval(
        id='interval-component',
        interval=5*1000, # 5秒刷新一次
        n_intervals=0
    ),
    html.Div(id='output1'),
    # 添加Store组件存储中间数据
    dcc.Store(id='cached-data')
])

# 第一个回调:监听下拉框和定时器,查询数据后缓存到Store,同时更新output1
@app.callback(
    [Output('output1', 'children'),
     Output('cached-data', 'data')],
    [Input('event-dropdown', 'value'),
     Input('run-dropdown', 'value'),
     Input('interval-component', 'n_intervals')]
)
def query_data(event_value, run_value, n):
    # 参数顺序和上面Input的顺序完全对应,直接拿来用就行
    # 这里写你的数据查询逻辑,用event_value和run_value作为查询条件
    D = {} # 替换为你的实际查询结果
    tab = []
    color_box = []
    Lap = []
    color_tab = []
    text = "查询完成,当前选择赛事:{},场次:{}".format(event_value, run_value)

    # 把要共享的中间数据打包成字典,序列化后存到Store
    cached_data = {
        "D": D,
        "tab": tab,
        "color_box": color_box,
        "Lap": Lap,
        "color_tab": color_tab
    }
    # 返回值数量和Output数量一致,第一个返回值对应output1的children,第二个对应cached-data的data
    return text, cached_data

# 第二个回调:从Store取缓存的数据,更新图表
@app.callback(
    Output('lapTime-graph', 'figure'),
    Input('cached-data', 'data')
)
def update_graph(cached_data):
    if not cached_data:
        return dash.no_update
    # 从缓存里取你需要的数据绘图
    D = cached_data["D"]
    Lap = cached_data["Lap"]
    # 替换为你的实际绘图逻辑,返回figure对象
    fig = {
        "data": [{"x": Lap, "y": [d.get("lap_time") for d in D], "type": "line"}],
        "layout": {"title": "圈速统计"}
    }
    return fig

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

如果不需要多回调共享数据,只是在同一个回调里完成查询+绘图,也可以直接把图表的Output加到第一个回调里,不用加Store组件,只要返回值数量和Output声明数量对应上即可。


内容的提问来源于stack exchange,提问作者MaxB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 23:27:03