表單是用來收集使用者輸入資料的重要 UI 元件, 本篇旨在測試 Streamlit 的兩個表單元件函式 st.form() 與表單提交按鈕函式 st.form_submit_button().
呼叫 st.form() 函式並傳入必要參數 key 會建立一個表單元件, 其參數結構如下 :
st.form(key, clear_on_submit=False, border=True)
| st.form() 參數 | 說明 |
|---|---|
key |
表單的唯一識別鍵 (必要參數),用來避免元件重複 (不顯示)。 |
clear_on_submit | 提交後是否清除欄位資料 (True/False, 預設 False)。 |
border |
是否顯示表單外框 (True/False, 預設 True)。自 Streamlit v1.18+ 起支援。 |
傳回值為一個 DeltaGenerator 容器物件, 它必須搭配 with 語法才能在表單中加入 UI 元件, 例如 :
with st.form(key='login_form'):
account=st.text_input('帳號:')
password=st.text_input('密碼:', type='password')
login=st.form_submit_button('登入')
表單元件 st.form() 內的最後一個 UI 元件通常是用來提交表單的 st.form_submit_button() 按鈕, 它的外觀與一般按鈕元件 st.button() 相同, 但功能上有所不同 :
- st.form_submit_button() 是設計來與 st.form() 搭配使用以實現延遲提交機制. 所謂延遲提交意思是表單中的所有輸入元件例如 st.text_input(), st.slider(), st.selectbox() 等在未按下提交按鈕之前, 其輸入值無法被程式邏輯取得.
- 雖然使用者可以即時操作這些輸入元件 (例如拖曳滑桿或輸入文字等), 元件也會即時顯示變化, 但只有當 st.form_submit_button() 被按下時整個表單區塊才會被一次提交並觸發頁面重新執行, 這時程式邏輯才能取得到輸入元件最新的值.
而一般按鈕 st.button() 則是即時觸發的元件, 一按就會讓整個頁面立刻 rerun, 因此若 UI 元件沒放在表單容器內, 則程式邏輯可以即時取得其輸入值.
提交按鈕的參數結構如下 (與一般按鈕相同) :
st.form_submit_button(label, key=None, help=None, on_click=None, args=None, kwargs=None, disabled=False, use_container_width=False)
參數說明如下表 :
| st.form_submit_button() 參數 | 說明 |
|---|---|
| label | 按鈕上顯示的文字(必耀參數)。 |
| key | 元件的唯一識別字串。用於避免與其他按鈕衝突。 |
| help | 滑鼠懸停時顯示的提示說明文字。 |
| on_click | 當按鈕被點擊時要呼叫的函式(通常搭配 callback 使用)。 |
| args | 傳入 on_click 的位置參數(tuple)。 |
| kwargs | 傳入 on_click 的關鍵字參數(dict)。 |
| disabled | 設為 True 時按鈕會呈現灰色並不可點擊。 |
| use_container_width | 設為 True 時按鈕會撐滿整個容器寬度。 |
例如 :
測試 1 : 預設的表單 [看原始碼]
# st-form-test-1.py
import streamlit as st
with st.form(key='login_form'):
account=st.text_input('帳號:')
password=st.text_input('密碼:', type='password')
if st.form_submit_button('取得表單輸入', type='primary'):
st.write(f'帳號:{account}')
st.write(f'密碼:{password}')
if st.button('取得表單輸入'):
st.write(f'帳號:{account}')
st.write(f'密碼:{password}')
此例在表單區塊內有一個提交按鈕; 外面則有一個一般按鈕, 初始化結果如下 :
在表單內輸入帳號密碼, 然後先按表單外的一般按鈕, 結果如下 :
由於表單尚未提交, 所以即使兩個文字欄位都有輸入資料, 但表單外的程式邏輯 (即一般按鈕的取值) 無法取得表單內的輸入值. 這時按下表單內的提交按鈕 :
可見表單提交會觸發程式 rerun 重新渲染網頁, 這時表單內的 if 為真因而輸出帳密, 表單外原來輸出的空帳密都被清除. 這時再次按下外面的一般按鈕會馬上觸發 rerun, 表單內原先的輸出會被清掉, 而原先提交的帳密資料還保存在 st.session_state 字典裡, 所以能夠取得其值 :
上例中的預設表單有邊界, 且提交後不會清除欄位內的輸入值, 下面範例測試參數 border=False 與 clear_on_submit=True 的效果 :
測試 2 : 參數 broder=False 與 clear_on_submit=True 的效果 [看原始碼]
# st-form-test-2.py
import streamlit as st
with st.form(key='login_form', border=False, clear_on_submit=True):
account=st.text_input('帳號:')
password=st.text_input('密碼:', type='password')
if st.form_submit_button('提交', type='primary'):
st.write(f'帳號:{account}')
st.write(f'密碼:{password}')
此例將參數 border 設為 False (無邊界), clear_on_submit 設為 True (提交後清除欄位), 下面是輸入欄位值尚未提交時, 可見表單無邊界 :
按下提交鈕後表單內的所有欄位都被清空 :
下面範例測試提交按鈕的 on_click 與 args 參數 :
測試 3 : 測試提交按鈕的 on_click 參數 [看原始碼]
# st-form-test-3.py
import streamlit as st
def on_submit_click():
account=st.session_state['account']
password=st.session_state['password']
st.session_state['login_info']=f'帳號:{account}\n\n密碼:{password}'
with st.form(key='login_form'):
account=st.text_input('帳號:', key='account')
password=st.text_input('密碼:', key='password', type='password')
st.form_submit_button(
'提交',
type='primary',
on_click=on_submit_click,
)
if 'login_info' in st.session_state:
st.write(st.session_state['login_info'])
此例於表單內的 st_text_input() 元件上添加 key 參數以便能於 st.session_state 字典中紀錄此兩欄位之值, 當按下提交按鈕時呼叫 on_submit_click(), 然後從 st.session_state 字典中取得欄位值產生輸出字串並記錄於 st.session_state 字典的 login_info 鍵, 結果如下 :
注意, 由於表單延遲提交特性, 如果把表單欄位值利用 args 或 kwargs 傳遞將無法取得輸入之值, 所以雖然提交按鈕 st.form_submit_button() 有 args 與 kwargs 這兩個參數, 但那只是繼承一般按鈕物件而來的, 它們在提交按鈕上沒有實質用處.







沒有留言 :
張貼留言