【问题标题】:callback in dash/plotly ignores if condition破折号/情节中的回调忽略条件
【发布时间】:2022-01-07 15:40:23
【问题描述】:

我遇到了 dash/plotly 的问题。我有一个带有输入框、按钮和图形区域的 html 页面。按下按钮后,我使用回调来更新图形(基于输入框条目)。但是,当我第一次加载我的页面时,尽管输入框为空,但似乎正在强制评估回调函数。因此我得到一个“回调错误更新...”。

这是我的代码:

layout = html.Div([
    dbc.Container([
        dbc.Row([
            dbc.Col(html.H1("1Y Stock Plot", className="text-center")
                    , className="mb-5 mt-5")
        ]),
       html.Div([
            dcc.Input(id='stockplot_symbol', placeholder='enter a stock ticker'),
            html.Button("Plot", id='submit_stockplot', n_clicks=0),
        ]),
        html.Div(id='output-graph')
    ])
])

和回调:

@app.callback(Output('output-graph', 'children'), #'stock_plot_graph', 'figure'),
              [Input('submit_stockplot', 'n_clicks')],
              [State('stockplot_symbol', 'value')]
              )
def update_stockplot(n_clicks, symbol):
    if n_clicks is not None:
        ticker = str(symbol).upper()

        df = yf.Ticker(ticker).history(period='1y', interval='1d')

        fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.1, row_heights=[0.7, 0.2])
        op = df['Open'].astype(float)
        hi = df['High'].astype(float)
        lo = df['Low'].astype(float)
        cl = df['Close'].astype(float)
        vo = df['Volume'].astype(float)

        upper, middle, lower = talib.BBANDS(cl, timeperiod=10, nbdevup=2, nbdevdn=2)

        fig.add_trace(go.Candlestick(x=df.index,
                                 open=op,
                                 high=hi,
                                 low=lo,
                                 close=cl, name=symbol), row=1, col=1)

        fig.add_trace(go.Scatter(x=df.index, y=upper, name='Upper Band'), row=1, col=1)
        fig.add_trace(go.Scatter(x=df.index, y=middle, name='Middle Band'), row=1, col=1)
        fig.add_trace(go.Scatter(x=df.index, y=lower, name='Lower Band'), row=1, col=1)
        fig.add_trace(go.Bar(x=df.index, y=vo, name='volume'), row=2, col=1)
        fig.update_layout(xaxis_rangeslider_visible=False,
                      height=800,
                      xaxis=dict(type="date"),
                      hovermode='x unified'
                      )
        return dcc.Graph(id='stock_plot_graph', figure=fig)
    else:
        return dash.exceptions.PreventUpdate

我确实在布局中将 n_clicks 设置为 0,但是 dash/plotly 以某种方式强制评估 if/else 语句中的内容,并且由于输入框中没有任何内容,因此数据框是空的,因此这会创建一个当我调用 talib.BANDS 时出现问题(这是函数 dash/plotly 抱怨回调错误更新... df 为空)

我的想法是仅在单击按钮时才更新或绘制图形区域。这在第一次调用后可以正常工作,但在第一次加载页面时就不行了。我尝试使用 if 语句来测试输入框是否为空,但得到相同的 callabck 错误。我可以设置一个初始/默认值来避免这种情况,但这对于我想做的事情来说并不是最佳的。我不想让回调中的函数在虚拟输入上进行评估,因为稍后该函数的处理时间不会像上述情况那样快。

你如何避免这种情况?

【问题讨论】:

    标签: python-3.x plotly-dash


    【解决方案1】:

    我的想法是仅在单击按钮时才更新或绘制图形区域。这在第一次调用后可以正常工作,但在第一次加载页面时就不行了。

    如果您想避免在页面加载时执行回调,您可以将回调的prevent_initial_call 属性设置为True

    Dash 应用程序中的所有回调在应用程序首次加载时使用其输入的初始值执行。这被称为回调的“初始调用”...您可以使用 prevent_initial_call 属性来防止回调在其输入最初出现在 Dash 应用程序的布局中时触发。此属性适用于 Dash 应用程序的布局最初加载时,以及在触发回调时将新组件引入布局时。

    https://dash.plotly.com/advanced-callbacks#prevent-callbacks-from-being-executed-on-initial-load

    【讨论】:

    • 感谢您指出这一点,这正是我想要的。我的意思是:仅在单击按钮时更新/显示图形;并且 prevent_initial_call 属性完成了这项工作。
    • 嗨 @bas-van-der-linden 感谢您回答 Plotly Dash 问题并支持我们的社区。亚当
    猜你喜欢
    • 2022-01-10
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 2021-12-20
    • 2021-10-14
    • 2012-08-07
    • 2020-11-09
    相关资源
    最近更新 更多