python - 破折号多个独立的回调
问题描述
我有一个简单的破折号应用程序,带有折线图和用作过滤器的单选按钮。
我创建了 2 个回调 - 第一个用于 url,第二个用于过滤器。但是,当我运行应用程序时,它一直在更新(我想在循环中调用第二个回调)。似乎这两个回调在某种程度上相互依赖,但我希望它们是独立的 - 我只需要在单选按钮(过滤器)更改时运行第二个。
没有第一个回调一切正常。
@app.callback(
Output('page-content', 'children'),
[Input('url', 'pathname')]
)
def display_page(pathname):
if pathname == '/':
return '404'
elif pathname == '/something/my-dashboard':
return app.layout
else:
return '404'
@app.callback(
Output("main-chart", "figure"),
Input("category", "value")
)
def update_graph(category):
dff = melted[melted["category"] == category]
fig = create_chart(dff)
set_style(fig, category)
return fig
编辑:添加布局
app.layout = html.Div(
[ dcc.Location(id='url', refresh=False),
html.Div(
[
html.Div(
[
html.H1(children="My dashboard"),
html.Div([dcc.Graph(id="main-chart", figure=fig)]),
],
className="column1",
),
html.Div(
[
dbc.Label("Filter", style={'fontWeight':'bold'}),
dcc.RadioItems(
id="category",
options=[{"label": i, "value": i} for i in categories],
value="Product A",
labelStyle={"display": "block"},
),
],
className="column2",
),
],
className="row",
id='page-content'
),
]
)
@BasvanderLinden 建议后的EDIT2:
fig = create_chart(df)
set_style(fig, "Marketing")
app.layout = html.Div(
[ dcc.Location(id='url', refresh=False),
html.Div(
className="row",
id='page-content'
),
]
)
dashboard_layout = html.Div(
[
html.Div(
[
html.H1(children="My dashboard"),
html.Div([dcc.Graph(id="main-chart", figure=fig)]),
],
className="column1",
),
html.Div(
[
dbc.Label("Category", style={'fontWeight':'bold'}),
dcc.RadioItems(
id="category",
options=[{"label": i, "value": i} for i in categories],
value="Marketing",
labelStyle={"display": "block"},
),
],
className="column2",
),
],
)
@app.callback(Output("page-content", "children"), [Input("url", "pathname")])
def display_page(pathname):
print(pathname)
if pathname == "/":
return "404"
elif pathname == "/my-dashboard":
return dashboard_layout
else:
return "404"
@app.callback(
Output("main-chart", "figure"),
Input("category", "value")
)
def update_graph(category):
dff = df[df["Category"] == category]
fig = create_chart(dff)
set_style(fig, category)
return fig
if __name__ == "__main__":
app.run_server(debug=True, host="0.0.0.0")
解决方案
The problem is actually in your first callback:
@app.callback(
Output('page-content', 'children'),
[Input('url', 'pathname')]
)
def display_page(pathname):
if pathname == '/':
return '404'
elif pathname == '/something/my-dashboard':
return app.layout
else:
return '404'
The problem is that you return app.layout
here.
It's actually really interesting what's happening here. Since app.layout
covers your whole layout, this means it will include the Location
component with an id value of url
as well. So since app.layout
is appended to the page-content
div, this means that after appending app.layout
to the page-content
div there are now two Location
components with the same id (url
). The fact that there is a new Location
components registered with id url
results in the callback being triggered again. This all results in the first callback being recursively triggered and appending elements to the dom. You can see this happening if you inspect the elements in the browser.
The solution therefore is to not return app.layout
in your callback, but to instead abstract a part of your layout and return that in the callback. That is a component that doesn't include a Location
component in its definition.
So you could abstract the dashboard in its own component something like this:
dashboard_layout = html.Div(
[
html.Div(
[
html.H1(children="My dashboard"),
html.Div([dcc.Graph(id="main-chart", figure=fig)]),
],
className="column1",
),
html.Div(
[
dbc.Label("Filter", style={"fontWeight": "bold"}),
dcc.RadioItems(
id="category",
options=[{"label": i, "value": i} for i in categories],
value="Product A",
labelStyle={"display": "block"},
),
],
className="column2",
),
]
)
app.layout = html.Div(
[
dcc.Location(id="url", refresh=False),
html.Div(
className="row",
id="page-content",
),
]
)
@app.callback(Output("page-content", "children"), [Input("url", "pathname")])
def display_page(pathname):
print(pathname)
if pathname == "/":
return "404"
elif pathname == "/something/my-dashboard":
return dashboard_layout
else:
return "404"
推荐阅读
- python - 如何将列表组合并转换为一个数据框?
- c# - 我正在尝试使用正则表达式捕获字符串。以下是我试图从中提取数据的文本文件示例
- javascript - 每当状态在本机反应中发生变化时,有没有办法将视图的背景颜色更改为 1 秒?
- r - 如果 column value == "character(0)" 从另一列取值
- python - 如何使用 Python 对每个流的 Wireshark TCP 数据包进行分组
- docker - 在启动时保留 docker 实例状态,并且不会丢失之前会话的工作
- jinja2 - Jinja2 if/else 对用户定义的变量
- scala - 在 spark scala 中使用 caseclass 与 structtype
- javascript - React 中的测试事件冒泡
- github - 如何通过 ssh 将 docker-compose 解决方案从 github 自动部署到 vps?