可視化ツールDashのチュートリアル - Part 3: State -


はじめに

前回のチュートリアルで、グラフを対話的に動作させる方法を学びました。

しかし、一般的なウェブページのログイン画面や会員登録画面を考えると、入力ボックスに情報を入力すると即座に反映されるのではなく、登録ボタンやログインボタンを入力することで情報が出力されます。

今回のチュートリアルで、こうした入力値をいったん止めておく機能を実装していきます。

公式HPのチュートリアル

Dash Input and Output

まずは前回の内容の復習として、入力ボックスを実装します。

まず最初に必要なライブラリをインポートします。

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

次にアプリの外観を決めていきます。

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Input(id="input-1", type="text", value="Montreal"),
    dcc.Input(id="input-2", type="text", value="Canada"),
    # 出力する場所
    html.Div(id="output")
])

次に入力値と出力値を決めていきます。

@app.callback(
    Output("output", "children"),
    [Input("input-1", "value"),
     Input("input-2", "value")]
)
def update_output(input1, input2):
    return "input 1 is {} and input 2 is {}".format(input1, input2)

if __name__ == "__main__":
    app.run_server(debug=True)

この例では、dash.dependencies.Inputの属性が変化した際に常にコールバック関数が動作してしまっています。

Dash State

上記の対策として、dash.dependencies.Stateを使います。この関数を使えばコールバックせずにデータの受け渡しが可能です。

では最初の例にボタンを導入したアプリを実装します。

まず必要なライブラリをインポートします。

import dash
import dash_core_components as dcc
import dash_html_components as html
# 追加でStateをインポート
from dash.dependencies import Input, Output, State

次にアプリの外観を決めていきます。

app = dash.Dash()

app.layout = html.Div([
    dcc.Input(id="input-1-state", type="text", value="Montreal"),
    dcc.Input(id="input-2-state", type="text", value="Canada"),
    html.Button(id="submit-button", n_clicks=0, children="Submit"),
    html.Div(id="output-state")
])

次に入力値と出力値、Stateを決めていきます。
イメージとして、いったんデータを送る前に入力値をStateさせ、ボタンが押されたらStateしてあるデータを出力するといった感じです。

@app.callback(
    Output("output-state", "children"),
    [Input("submit-button", "n_clicks")],
    [State("input-1-state", "value"),
     State("input-2-state", "value")]
)
def update_output(n_clicks, input1, input2):
    return """
        The Button has been pressed {} times,
        Input 1 is {},
        and Input 2 is {}
    """.format(n_clicks, input1, input2)


if __name__ == '__main__':
    app.run_server(debug=True)

この例を見てみると、dcc.Inputの入力ボックスに文字が入力されてもコールバックは起きず、ボタンを押したときにコールバックが発生し入力値が更新されています。

今回コールバックを発生させている箇所は、html.Buttonコンポーネントに存在しているn_clicksプロパティです。このプロパティは、コンポーネントの部分がクリックされるたびに1ずつ増加していきます。

このプロパティは、dash_html_componentsライブラリのすべてのコンポーネントで使用できます。