【Dash】如何在callback中 传入多个input 和 输出多个output(或者动态生成)

方法一:通过函数传参完成:

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 wrapper

    return accept_func

inputs = [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 code
    return

我在这里讲解一下 其中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, State

external_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 duplication
    return 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 wrapper
    return 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_context

    if not ctx.triggered:
        return ""
    else:
        button_id = ctx.triggered[0]["prop_id"].split(".")[0]
    print(button_id)
    print(kwargs)
    i = 0
    ans = []
    for arg in kwargs:
        i = i+1
        if 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:
            break
    return ans

if __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, List

import dash
from dash.dependencies import Input, Output, State

app = 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~

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值