我对Dash相对来说是个新手,我觉得我对回调理解得很好。但是,我现在的情况是,似乎需要在一个回调中调用所有回调,因为当调用该回调时,我的程序工作正常。
当我有多个回调时,它们各自都能很好地工作;这意味着如果我注释掉一个回调,回调就会按需要工作。我能够使用context.triggered获得正确的功能,但我不想在一个大规模回调中得到所有的东西,我觉得这是我理解的一个问题。我尝试过限制回调的一个输入,但这仍然不起作用。我是否将整个应用程序布局传递给回调?
如果是,如何限制在I之外传递的内容?怎么回事?
以下是一个经过调整的工作实例:
import dash
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
import dash_table
from dash.dependencies import Input, Output, State
import plotly.express as px
from dash import callback_context, no_update
import webbrowser
from flask import request
chrome_path = 'C:/Program Files (x86)/Google/Chrome/Application/chrome.exe %s'
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/Mining-BTC-180.csv").drop('Unnamed: 0',axis=1)
selected_cols = ['Number-transactions', 'Output-volume(BTC)',
'Market-price', 'Hash-rate', 'Cost-per-trans-USD', 'Mining-revenue-USD',
'Transaction-fees-BTC']
class Parameter_Viewer():
def __init__(self, df, **kwargs):
revenue_plot = px.scatter(df, x="Date", y="Mining-revenue-USD",title='Mining-revenue-USD')
Hash_plot = px.scatter(df, x="Date", y="Hash-rate",title='Hash-rate')
parameter_table = dash_table.DataTable(
id='db-table',
columns=[{"name": i, "id": i} for i in selected_cols],
data=df.to_dict('records'),
#page_action="native",
page_action='none',
style_table={'height': '300px', 'overflowY': 'auto'},
editable=True
)
app = dash.Dash()
app.layout = html.Div(
children=[
#first row
html.Div(
children=[
html.Div(children=[
html.H1("Parameter", className="menu-title"),
dcc.Dropdown(
id="parameter-filter",
options=[
{"label": parameter, "value": parameter} for parameter in df.columns
],
value="Mining-revenue-USD",
clearable=False,
className="dropdown",
),]),
html.Div(children=[
html.H1("Data Type", className="menu-title"),
dcc.Dropdown(
id="data-selector",
options=[
{"label": data_col, "value": data_col} for data_col in selected_cols
],
value="Hash-rate",
clearable=False,
className="dropdown",
),]),
html.Button("Close Viewer", id="Close_Btn")
]
),
html.Div(children=[
html.H1(children="Database Analytics",),
parameter_table]),
html.Div(children=[
html.Div(
dcc.Graph(id='param-plot',figure=revenue_plot),
style={"width":'50%', "margin": 0, 'display': 'inline-block'},className="six columns"),
html.Div(
dcc.Graph(id='param-plot2',figure=Hash_plot),
style={"width":'50%', "margin": 0, 'display': 'inline-block'},className="six columns")],className="row")
])
@app.callback(
[Output("db-table", "data"), Output("param-plot", "figure"), Output("param-plot2", "figure")],
[Input("parameter-filter", "value"),Input("data-selector", "value"),Input('db-table', 'data')])#,prevent_initial_call=True)
def update_charts(parameter,data_type,table_data):
changed_inputs = [x["prop_id"]for x in callback_context.triggered]
if changed_inputs[0] == 'parameter-filter.value':
df = pd.DataFrame.from_dict(table_data)
ua_plot = px.scatter(df, x="Date", y=data_type)
aa_plot = px.scatter(df, x="Date", y=parameter)
return table_data, ua_plot, aa_plot
elif changed_inputs[0] == 'db-table.data':
df = pd.DataFrame.from_dict(table_data)
ua_plot = px.scatter(df, x="Date", y=data_type)
aa_plot = px.scatter(df, x="Date", y=parameter)
return no_update, ua_plot, aa_plot
else:
return no_update,no_update,no_update
@app.callback(Output("db-table", "data"),Input("Close_Btn", "n_clicks"),prevent_initial_call=True)
def close_browser(n_clicks):
print('In close callback\n')
if n_clicks>0:
self.shutdown()
return no_update
host='127.0.0.1'
port='8050'
url = 'http://{}:{}/'.format(host,port)
webbrowser.get(chrome_path).open(url)
app.run_server(debug=False)
def shutdown(self):
func = request.environ.get('werkzeug.server.shutdown')
if func is None:
raise RuntimeError('Not running with the Werkzeug Server')
func()
Parameter_Viewer(df)```发布于 2021-08-23 09:27:58
更容易考虑回调的基本情况,然后再对它们进行扩展。根据我的经验,我通常构造回调的主要原因是处理由特定输入引起的特定输出。
例如。
如果输出O1是输入I1的效果,那么我将进行回调C1(I1→O1)。
如果输出O1是输入I1和I2的影响,则进行回调C1(I1,I2→O1)。
如果您碰巧有多个输出是一个输入的影响,那么您可以将这些输出组合在同一个回调中。
例如。
如果输出O1是输入I1的影响,而输出O2是输入I1的效果,那么就进行回调C1(I1→O1,O2)。
另外,请记住,Dash不允许多个回调具有相同的输出组件(例如,特定组件属性可以与一个且只有一个回调相关联)。在这种情况下,如果您的特定输出需要与另一个输出同时更新,但不一定是同一输入的影响,那么您仍然应该将输出合并到单个回调中。
例如。
如果输出O1是输入I1的影响,而输出O2必须用O1更新,那么我将创建一个回调C1(I1→O1,O2)。
我不知道为什么在注释中尝试使用State()而不是but (),因为State()在仍然必须被读取为输入的情况下使用State(),但不一定需要触发。
所以使用上面的逻辑,例如,
如果输出O1是输入I1的效果,而不是输入(我们现在称为状态) S1的效果,但仍然需要S1,那么我将进行回调C1(I1,S1→O1)。
通常情况下,有大量的回调具有许多输入和输出,只要回调不试图一次做太多不连贯的事情(否则,当您回过头来查看代码时,您将花费大量时间来记住您相信我的话:)。
发布于 2021-12-03 10:45:53
如果你像我一样是个初学者。你可能在寻找最有价值的信息,就我而言,在Daniel 的回答中:
Dash不允许多个回调具有相同的输出组件
https://stackoverflow.com/questions/68820651
复制相似问题