pythonsession-statestreamlit

Difficulty initializing complex session_state for inputs in Streamlit


This is my code and although I initialize the session state, I'm having a conflict with it.

import streamlit as st

if "user_inputs" not in st.session_state:
    st.session_state["user_inputs"] = True

# Loop over the 8 questions
for i in range(8):
    # Get the question
    question = f'Question {i+1}'
    # Add it to the page
    st.subheader(question)
    
    # Create 3 checkbox options
    checkbox1 = st.checkbox('Option 1')
    checkbox2 = st.checkbox('Option 2')
    checkbox3 = st.checkbox('Option 3')
    
    # Save the checkbox inputs in the session state object
    
    st.session_state.user_inputs[f'{question}_checkbox_1'] = checkbox1
    st.session_state.user_inputs[f'{question}_checkbox_2'] = checkbox2
    st.session_state.user_inputs[f'{question}_checkbox_3'] = checkbox3
    
    # Create an integer input
    integer_input = st.number_input('Integer Input')
    
    # Save the integer input in the session state object
    st.session_state.user_inputs[f'{question}_integer_input'] = integer_input
    
# Create a slider
slider = st.slider('Slider', 0, 100)

# Save the slider value in the session state object
st.session_state.user_inputs['slider'] = slider

# Add a submit button
if st.button('Submit'):
    st.success('Form submitted!')

I tried different ways to initialize but they didn't work. When I try something like st.session_state.user_inputs = "test" or st.session_state["user_inputs"] = "test", again I have same error:

The error is:

st.session_state has no attribute "user_inputs". Did you forget to
initialize it? More info:
https://docs.streamlit.io/library/advanced-features/session-state#initialization

I tried to create a kind of form but I received a repetitive error.


Solution

  • The error I get for your main block of code is TypeError: 'bool' object does not support item assignment.

    This makes sense, because st.session_state["user_inputs"] = True means you've set up a boolean, not a dictionary, so when you do:

    st.session_state.user_inputs[f'{question}_checkbox_1'] = checkbox1
    

    you're basically doing:

    True[f'{question}_checkbox_1'] = checkbox1
    

    giving the error. Instead, use:

    if "user_inputs" not in st.session_state:
        st.session_state["user_inputs"] = {}
    

    Next, you have duplicate keyed inputs. Try adding unique keys to these:

    checkbox1 = st.checkbox('Option 1', key=f'{i}-1')
    checkbox2 = st.checkbox('Option 2', key=f'{i}-2')
    checkbox3 = st.checkbox('Option 3', key=f'{i}-3')
    
    # ...
    
    integer_input = st.number_input('Integer Input', key=i)
    

    Note also that keyed user inputs are automatically added to state, which is a bit surprising, but that's Streamlit for you. If you do prefer to explicitly set them, I'd use actual nested structures like 2d lists or dicts rather than keys with concatenated identifiers.

    Finally, you may want to use st.form to group all of your inputs into a collection, avoiding triggering rerenders.