方法一:通过函数传参完成:
def dash_kwarg(inputs):def accept_func(func):@wraps(func)def wrapper(*args):input_names = [item.component_id for item in inputs]kwargs_dict = dict(zip(input_names, args))return func(**kwargs_dict)return wrapperreturn accept_funcinputs = [Input("plot-button", "n_clicks")]states = [[State('input1', 'on'),State('input2','value'),.........State('input22','value'),]@app.callback(Output(component_id='cluster-table', component_property='children'),inputs,states,
)
@dash_kwarg(inputs + states)
def generate_graph(**kwargs)://some code....kwargs['input10']....//some codereturn
我在这里讲解一下 其中dash_kwarg,相当于包装函数,把inputs和states包装之后传到generate_graph里。我们可以通过输出kwargs来看看中间到底有什么内容。在这里我自己写了一个完整的代码, 大家可以在app.py中跑一下,看看这个函数到底做了什么。
from functools import wraps
from typing import Any, Callable, List
import dash_html_components as html
import dash_bootstrap_components as dbc
import dash
from dash.dependencies import Input, Output, Stateexternal_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css',dbc.themes.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)text = ["sugar", "yes, please", "DeanWinchester", "Castiel Novak", "SamWinchester"]#这里用了dash bootstrap component里的collapse 看不懂无所谓,只需要输出kwargs查看即可
def make_item(i):# we use this function to make the example items to avoid code duplicationreturn dbc.Card([dbc.CardHeader(html.H2(dbc.Button(f"Collapsible group #{i}",color="link",id=f"group-{i}-toggle",))),dbc.Collapse(dbc.CardBody(f"This is the content of group {i}..{text[i]}"),id=f"collapse-{i}",),])
accordion = html.Div([make_item(i) for i in range(1, 5)], className="accordion"
)
app.layout = html.Div([accordion]
)def dash_kwarg(inputs):def accept_func(func):@wraps(func)def wrapper(*args):input_names = [item.component_id for item in inputs]kwargs_dict = dict(zip(input_names, args))return func(**kwargs_dict)return wrapperreturn accept_func#inputs = [Input("plot-button", "n_clicks")]#states = [[State('input1', 'on'), State('input2','value'), State('input22','value')]]
length = 5
outputs = [Output(f"collapse-{i}", "is_open") for i in range(1, 5)]
inputs = [Input(f"group-{i}-toggle", "n_clicks") for i in range(1, 5)]
states = [State(f"collapse-{i}", "is_open") for i in range(1, 5)]
@app.callback(outputs,inputs,states,
)
@dash_kwarg(inputs + states)
def generate_graph(**kwargs):ctx = dash.callback_contextif not ctx.triggered:return ""else:button_id = ctx.triggered[0]["prop_id"].split(".")[0]print(button_id)print(kwargs)i = 0ans = []for arg in kwargs:i = i+1if i <= (length-1):if arg == button_id:v = kwargs[button_id]if v == None:ans.append(False)elif v%2 == 0:ans.append(False)else:ans.append(True)else:ans.append(False)else:breakreturn ansif __name__ == '__main__':app.run_server(debug=True, port=8055)
输出的kwargs,可以看出是输出的input+state的内容,只不过换成了字典形式,通过上述包装函数。然后在generat_graph中对各个input和state进行操作,最后返回列表形式的output即可。
有人把上面的代码整理成了一个更加简洁的版本,但是我没看懂,需要深究的小伙伴可以自己参考。
简洁版:
from functools import wraps
from typing import Any, Callable, Listimport dash
from dash.dependencies import Input, Output, Stateapp = dash.Dash(__name__)def handler(outputs: List[Output], inputs: List[Input], states: List[State]):def accept_func(func: Callable[[Any], Any]):@app.callback(outputs, inputs, states)@wraps(func)def wrapper(*args: Any):input_names = [d.component_id + "--" + d.component_property for d in inputs + states]kwargs_dict = dict(zip(input_names, args))return func(**kwargs_dict)return accept_func
讨论的帖子在这里:https://community.plot.ly/t/how-to-elegantly-handle-a-very-large-number-of-input-state-in-callbacks/19228/5
欢迎使用dash的同学,用好community~