st.form() メソッドを利用しよう

Streamlit は、画面上に入力欄やボタンなどのコンポーネントを簡単に配置することができますが、ユーザーによる操作やフロント側のコード変更のたびに、すべてのスクリプトが再実行される仕組みになっています。

たとえば、入力欄をいくつか配置し、ボタンをクリックしたタイミングで画面表示を切り替える画面を作っても、入力欄の値を変えるだけでスクリプトが再実行され、画面全体がリフレッシュされてしまうため、それまでの内容が消えてしまいます。

そこで今回は st.form() を使ってフォームコンテナを実装し、ボタンをクリックするまで画面を更新しない手法をご紹介します。
前回に引き続き、環境は以下の通りです。

python 3.10.11
streamlit 1.25.0

入力欄とボタンだけを設置してみる

はじめに、日付入力コンポーネントとボタンだけを配置した画面を作ってみます。

  • st.date_input() に以下のような初期値で [検索日付] 欄を配置
  • st.button() で [照会] ボタンを配置
  • [照会] ボタンクリック時に [検索日付] 欄の値をテキスト表示するように設定
    (ボタンの下の (datetime.date(2023, 8, 6), datetime.date(2023, 8, 13)) の部分に、入力した日付がテキスト表示される)
st.date_input() の設定初期値
ラベル検索日付
From 日付の初期値システム日付の7日前
To 日付の初期値システム日付
Session State の key(※)date_input_find
※ Session State はセッション内に値を保持することができる機能です。
  詳しくは公式ページをご参照ください。

  https://docs.streamlit.io/library/api-reference/session-state

実際のコードは以下のようになります。

import streamlit as st
import datetime

# ページレイアウトとタイトルの設定
st.set_page_config(
  page_title='Streamlitでアプリ構築',
  page_icon='🔎',
  layout='wide'
)
st.subheader('Streamlitでアプリ構築')

# st.date_inputコンポーネント(検索日付)を配置
st.date_input(
  label='検索日付',
  value=[
    datetime.datetime.now() - datetime.timedelta(7),
    datetime.datetime.now()
  ],
  key='date_input_find'
)
# 照会ボタンを押下した場合
if st.button("照会"):    
    # st.date_inputのセッションステートの内容をテキスト表示
    st.write(st.session_state['date_input_find'])

この状態で動かしてみると、下図のように [照会] ボタンクリック後に日付を変更するだけでテキスト部分がクリアされ、元の値(2023/08/06 ~ 2023/08/13)が消えてしまうのがわかります。

フォームを設置

ここで st.form() を使って、同じ画面を作成してみます。
st.form() は、ユーザー入力欄と submit ボタンを含むフォームを簡単に実装できるコンポーネントです。submit ボタンが押されるまでフォーム内のコンポーネントは変化せず、ボタンクリック時にまとめて再描画されます。

st.form() の引数は以下の2つです。

st.form() の引数内容
keySession Stateのkey
(デフォルトはNone)
clear_on_submitTrueにするとボタンクリック時にすべての値がクリアされる
(デフォルトはFalse)

実際のコードは以下のようになります。

import streamlit as st
import datetime

# ページレイアウトとタイトルの設定
st.set_page_config(
  page_title='Streamlitでアプリ構築',
  page_icon='🔎',
  layout='wide'
)
st.subheader('Streamlitでアプリ構築')

# フォームを配置
with st.form(key='form_find', clear_on_submit=False):
  # st.date_inputコンポーネント(検索日付)を配置
  st.date_input(
    label='検索日付',
    value=[
      datetime.datetime.now() - datetime.timedelta(7),
      datetime.datetime.now()
    ],
    key='date_input_find'
  )
  # st.form_submit_buttonコンポーネント(照会ボタン)を配置
  # (formにボタンを置く場合は st.buttonをst.form_submit_buttonに置き換える)
  submit_inquiry = st.form_submit_button("照会")
    
  # 照会ボタンを押下した場合
  if submit_inquiry:
    # st.date_inputのセッションステートの内容をテキスト表示
    st.write(st.session_state['date_input_find'])

このコードをブラウザで動かしてみたのが下図になります。
前項と見た目は同じですが、[照会] ボタンをクリックするまで、日付のテキスト表示が残っていることが確認できました。

次回は検索フォームをサイドバーに表示します。