Streamlit Flow interactions

:rotating_light: Before clicking “Create Topic”, please make sure your post includes the following information (otherwise, the post will be locked). :rotating_light:

  1. Local development by now
  2. Not deployed
  3. Not much dependencies in the example
  4. No error message but behaves as not intended.
  5. Streamlit 1.8.1 python 3.10.2

I am deploying app which performs various actions for the user…
I am unfortunately facing issues (sometimes, not always) with streamlit object interaction in the app flow…
I know the streamlit rerun app every time user action is performed.

So I have as similar example app/action which should
As soon as you enter the username, it validates it.
If valid, it will check the username in DB…|
If found in DB (check passed) it should displau dropdown selectbox with at least two aciton
(In reality it will be disable and enable user in DB)
However the action method after selecting action from dropdown is not called or
If a tried with session states i get lost in circle, either the selec box dropdown was there from the very start or none, or action hasn’t been called again…

Now I removed all session states,
Accommodate the code to similar (simple methods)
If anyone could help me to fix it, I will be happy
(username is validate against surrname_firstcharoffirstname like eg, smith_j)

import time
import streamlit as st
import re


def main():
    st.info('Starting to DISABLE User')
    app_disable_user_show_form()


def validate_user_form(user):
    pattern = r'[a-z]+_[a-z]{1,2}$'    # eg: smith_j
    if user == '' or user is None:
        st.error("Username is empty !")
        return False
    if not re.match(pattern, user):
        st.error("The username specified deosn't match USER pattern !")
        return False
    return True


def app_check_user_id_start(env, user):
    pattern = r'test.*'
    user_id_test = 100 if re.match(pattern, user) else 200
    mess = f'User {user.upper()} successfully found in {env.upper()} DB'
    enabled = 'ENABLED'
    status_test = True
    return status_test, user_id_test, enabled, mess


def app_disable_user_show_form():
    with st.form("username_form"):
        entered = st.text_input("enter username (eg.: test_u)")
        check_button = st.form_submit_button('check user')

    if check_button:
        user = user_lc = entered.lower()    # lowercase username
        user_uc = entered.upper()           # uppercase username
        valid = validate_user_form(user_lc)
        if not valid:
            return
        st.markdown(f'<h5 style="color: #eb8c2c;">Checking User {user}in DB</h5>', unsafe_allow_html=True )
        env = 'test'
        st.info(f"Checking user in {env.upper()} DB")
        status_test, user_id_test, enabled, mess = app_check_user_id_start(env, user)
        if status_test:
            st.info(f'User "{user}" found with ID: {user_id_test}')
        else:
            return

               if user_id_test > 1:
            # user_info = st.session_state.user_data
            st.success(f"Consistency check PASSED.   User {user} with ID:{user_id_test}  OK", icon='✅')
            action = st.selectbox("Select an action", ["", "Action 1", "Action 2", "Action 3"], key="selected_action")
            if action:
                app_perform_action(action, user)


def app_perform_action(action, user):
    if action == "Action 1":
        method_for_action_1(user)
    if action == "Action 2":
        method_for_action_2(user)
    if action == "Action 3":
        method_for_action_3(user)


def method_for_action_1(user):
    st.info('You are in the Action 1  Branch')


def method_for_action_2(user):
    st.info('You are in the Action 2 Branch')


def method_for_action_3(user):
    st.info('You are in the Action 3 Branch')



if __name__ == "__main__":
    main()

You have a button in the form, and a select box after that.

Sample Events

  1. Fillup the form and press the button.

  2. ST reruns the code from the top.

  3. The value of check_button is true so it will read the code behind it.

  4. You reach the selectbox, and select an action.

  5. ST reruns the code from the top.

  6. This time the value of check_button is false. So the action was not executed as we had expected.

One way to fix this in this particular case is to study how to bypass the button in the form. The form validates the user. If user is ok, we don’t need it anymore. There is a local variable status_test, we can copy its status in the session state.

At the top, declare and initialize a session variable called status_test.

if 'status_test' not in st.session_state:
    st.session_state.status_test = False

In the check_button line add the status_test condition.

if check_button or st.session_state.status_test:
    # blah

And update the status_test.

if status_test:
    st.session_state.status_test = True  # this
    st.info(f'User "{user}" found with ID: {user_id_test}')

So if ST reruns the code from the top and session variable status_test is true, we can pass thru the check_button because we have the or condition in place.

You are more familiar with your code, there can be other solutions to fix it.

Sample output

You are absolutely right. Got it. It makes sense.
I needed right code to understand and you helped me a lot.
So Ferdy, thank you and Happy New YEAR !

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.