はじめにのインタラクティブ機能 で確認できるように、1つのコールバック関数は複数の入力を受け入れることができますが、常に単一の出力を持ちます。
入力の変更後に更新する必要がある2つのブロックが別々にあると想定します。もちろん、最も簡単な方法は、ブロックごとに同じ入力で2つのコールバックを作成することです。問題は、リクエストが2回実行される一方で、1つですべてのデータを取得できることです。
@app.callback(
dash.dependencies.Output('element_1', 'children'),
[dash.dependencies.Input('filter', 'value')])
def callback_element_1(filter):
return get_data(filter).el1
@app.callback(
dash.dependencies.Output('element_2', 'children'),
[dash.dependencies.Input('filter', 'value')])
def callback_element_2(filter):
return get_data(filter).el2
私が見つけた解決策は、これらの要素を単一のブロックでラップし、単一のリクエストで完全に再レンダリングすることです。ただし、この場合、特に初期要素がDOMで互いに離れている場合は、ラッパー内のすべての静的コンテンツも更新されます。
@app.callback(
dash.dependencies.Output('wrapper', 'children'),
[dash.dependencies.Input('filter', 'value')])
def callback_element_wrapper(filter):
data = get_data(filter)
return html.Div(
children=[
data.el1,
# more static content
data.el2,
]
)
たぶん、単一のリクエストで2つ以上の要素に出力するよりエレガントな方法があるでしょうか?
現在、Plotly Dashは1つのイベントで複数の出力をサポートしています。これはdash == 0.38.0rc1の最新バージョンです。
enter code `@app.callback([Output('output1', 'children'), Output('output2', 'children')],
[Input('output-btn', 'n_clicks')],
[State('output-btn', 'n_clicks_timestamp')])
def on_click(n_clicks, n_clicks_timestamp):
if n_clicks is None:
raise PreventUpdate
return n_clicks, n_clicks_timestamp`
this に基づいて、方法があります。
実行できることは、非表示の「信号要素」(これはたとえばテキスト入力である場合があります)を更新することです。これにより、2つの主要な要素が更新されます。
get_data(filter)
を1回実行し、結果をグローバル変数に格納します。次に、element_1
およびelement_2
を更新する代わりに、その信号要素を更新します。
result = []
@app.callback(
dash.dependencies.Output('signal', 'value'),
[dash.dependencies.Input('filter', 'value')])
def callback_signal(filter):
global result
result = get_data(filter)
return filter
@app.callback(
dash.dependencies.Output('element_1', 'children'),
[dash.dependencies.Input('signal', 'value')])
def callback_element_1(filter):
return result.el1
@app.callback(
dash.dependencies.Output('element_2', 'children'),
[dash.dependencies.Input('signal', 'value')])
def callback_element_2(filter):
return result.el2
私の場合、シングルユーザー環境でDashを使用しており、グローバル変数の使用は問題になりませんでした。同時にアプリを実行する複数のユーザーがいる場合、代わりの方法が利用可能であり、同じリンクでそれらを見つけることができます。
外部の関数でアクションリスナーを構成できるとしたらどうでしょうか?オレーの例を使う
def setup_action_callbacks(app):
result = []
@app.callback(
dash.dependencies.Output('signal', 'value'),
[dash.dependencies.Input('filter', 'value')])
def callback_signal(filter):
result = get_data(filter)
return filter
@app.callback(
dash.dependencies.Output('element_1', 'children'),
[dash.dependencies.Input('signal', 'value')])
def callback_element_1(filter):
return result.el1
@app.callback(
dash.dependencies.Output('element_2', 'children'),
[dash.dependencies.Input('signal', 'value')])
def callback_element_2(filter):
return result.el2
そのような:
def get_app_layout(app):
setup_action_callbacks(app)
return html.Div()
app = DjangoDash(name="a_Nice_name", app_name="a_Nice_app_name")
app.layout = get_app_layout(app)
マルチ出力コールバックのサポートがDashに統合されました(2019/03/01)。
GitHubプルリクエストを参照してください: Multi output callbacks support
お知らせをご覧ください: Dashの複数の出力-利用可能になりました!