在动态生成组件时,Plotly Dash 应用程序似乎没有更新 app.layout 属性
Plotly Dash app doesen't seem to update the app.layout property when generating components on the fly
Dash 在从回调动态创建组件时似乎不会更新 app.layout 属性。下面是一个重现不良行为的简单示例:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
html.Button(id="display_graph",children="Show graph"),
html.Div(children='''
Dash: A web application framework for Python.
'''),
html.Div(id="graph_div", children=[]),
html.Div(id="detiles", children=[])
])
@app.callback(
Output('detiles', 'children'),
[Input('graph', 'hoverData')])
def debug_hover(hover_data):
children = []
print(hover_data)
if hover_data["points"] is not None:
points = hover_data["points"]
for p in points:
print(p["curveNumber"])
trace_name = app.layout['graph'].figure['data'][p["curveNumber"]]['name']
# trace_name = "placeholder"
children.append(html.Div(
[html.P(f"Estimated Turnover:{trace_name}: {p['value']}", style={"display": "inline-block"})]))
return children
@app.callback(
Output(component_id='graph_div', component_property='children'),
[Input(component_id='display_graph', component_property='value')]
)
def update_output_div(input_country):
x = [1,2,3,4,5,6,7,8]
y1 = [i*2 for i in x]
y2 = [i * 3 for i in x]
y3 = [i * 4 for i in x]
fig = {
'data': [
{'x': x, 'y': y1, 'type': 'bar', 'name': 'Basic model',
"marker_color": 'rgb(55, 83, 109)'},
{'x': x, 'y': y2, 'type': 'bar', 'name': 'New model',
"marker_color": 'rgb(185, 83, 109)'},
{'x': x, 'y': y3, 'type': 'bar', 'name': 'Model V2',
"marker_color": 'rgb(32, 201, 52)'}
],
'layout': {
'title': f"{input_country}",
'xaxis': {'rangeslider': {"visible": True},
'range': [0, 20]},
'height': 700,
'width': 1200,
'margin': {'b': 400}
}
}
graph = dcc.Graph(id="graph", figure=fig)
return graph
if __name__ == '__main__':
app.run_server(debug=True)
我在破折号调试器中遇到的错误如下所示:
这意味着 app.layout
中没有“graph”元素,但显然“graph_div”组件中的 children 下应该有一个“graph”。该图是通过回调创建的并且清晰可见。
即使我检查 PyCharm 中的调试器并检查 app.layout,我发现“graph_div”子项中没有预期的 dcc.Graph 组件
这是预期的行为还是需要调查的错误?如果是预期的,是否有任何解决方法来访问动态生成的组件的属性,例如现有图形中的跟踪名称?
我发现我应该将 State
传递给回调。如下所示修改 debug_hover
解决了我的问题:
@app.callback(
Output('detiles', 'children'),
[Input('graph', 'hoverData')],
[State("graph","figure")] # This was modified
)
def debug_hover(hover_data,figure): # This was modified
children = []
print(hover_data)
if hover_data["points"] is not None:
points = hover_data["points"]
for p in points:
print(p["curveNumber"])
trace_name = figure['data'][p["curveNumber"]]['name'] # This was modified
# trace_name = "placeholder"
children.append(html.Div(
[html.P(f"Estimated Turnover:{trace_name}: {p['value']}", style={"display": "inline-block"})]))
return children
Dash 在从回调动态创建组件时似乎不会更新 app.layout 属性。下面是一个重现不良行为的简单示例:
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div(children=[
html.H1(children='Hello Dash'),
html.Button(id="display_graph",children="Show graph"),
html.Div(children='''
Dash: A web application framework for Python.
'''),
html.Div(id="graph_div", children=[]),
html.Div(id="detiles", children=[])
])
@app.callback(
Output('detiles', 'children'),
[Input('graph', 'hoverData')])
def debug_hover(hover_data):
children = []
print(hover_data)
if hover_data["points"] is not None:
points = hover_data["points"]
for p in points:
print(p["curveNumber"])
trace_name = app.layout['graph'].figure['data'][p["curveNumber"]]['name']
# trace_name = "placeholder"
children.append(html.Div(
[html.P(f"Estimated Turnover:{trace_name}: {p['value']}", style={"display": "inline-block"})]))
return children
@app.callback(
Output(component_id='graph_div', component_property='children'),
[Input(component_id='display_graph', component_property='value')]
)
def update_output_div(input_country):
x = [1,2,3,4,5,6,7,8]
y1 = [i*2 for i in x]
y2 = [i * 3 for i in x]
y3 = [i * 4 for i in x]
fig = {
'data': [
{'x': x, 'y': y1, 'type': 'bar', 'name': 'Basic model',
"marker_color": 'rgb(55, 83, 109)'},
{'x': x, 'y': y2, 'type': 'bar', 'name': 'New model',
"marker_color": 'rgb(185, 83, 109)'},
{'x': x, 'y': y3, 'type': 'bar', 'name': 'Model V2',
"marker_color": 'rgb(32, 201, 52)'}
],
'layout': {
'title': f"{input_country}",
'xaxis': {'rangeslider': {"visible": True},
'range': [0, 20]},
'height': 700,
'width': 1200,
'margin': {'b': 400}
}
}
graph = dcc.Graph(id="graph", figure=fig)
return graph
if __name__ == '__main__':
app.run_server(debug=True)
我在破折号调试器中遇到的错误如下所示:
app.layout
中没有“graph”元素,但显然“graph_div”组件中的 children 下应该有一个“graph”。该图是通过回调创建的并且清晰可见。
即使我检查 PyCharm 中的调试器并检查 app.layout,我发现“graph_div”子项中没有预期的 dcc.Graph 组件
这是预期的行为还是需要调查的错误?如果是预期的,是否有任何解决方法来访问动态生成的组件的属性,例如现有图形中的跟踪名称?
我发现我应该将 State
传递给回调。如下所示修改 debug_hover
解决了我的问题:
@app.callback(
Output('detiles', 'children'),
[Input('graph', 'hoverData')],
[State("graph","figure")] # This was modified
)
def debug_hover(hover_data,figure): # This was modified
children = []
print(hover_data)
if hover_data["points"] is not None:
points = hover_data["points"]
for p in points:
print(p["curveNumber"])
trace_name = figure['data'][p["curveNumber"]]['name'] # This was modified
# trace_name = "placeholder"
children.append(html.Div(
[html.P(f"Estimated Turnover:{trace_name}: {p['value']}", style={"display": "inline-block"})]))
return children