How do I keep randomly generated values persistent, except for when users uncheck and recheck a box?

I am building an app where users can choose to either supply values themselves or have value randomly generate, using the random option with st.checkbox. There are also several options users can select with a dropdown menu.

Currently, if a user checks the random box and then changes the menu, the random values will re-generate. And, even worse, if a user presses to button to get a result, it also random re-generates values. I am trying to find out the most direct option to keep these persistent (a) when someone presses the button and (b) when something else is changed. However, ideally (c) the random values will regenerate when someone unchecks and re-checks the random box.

I know there is some solution with st.session_state, which I have used with buttons in the past, but I am totally flummoxed with how to get what I am looking for with st.checkbox and the on_change parameter.

Below is a minimal reproducible example with a simple calculator app:

import streamlit as st 
import random

operation = st.selectbox("Which type of operation shall we do for the numbers 1 and 2?",["add","subtract","multiply","divide"])

if st.checkbox("Randomly generate my numbers"): 
        num1 = random.randint(0,20) 
        num2 = random.randint(0,20) 
        st.write(f"Your random numbers are: `{num1}` and `{num2}`.")

else: 
    num1 = st.number_input("What is the first number?",min_value=0,max_value=20,key="num1") 
    num2 = st.number_input("What is the second number?",min_value=0,max_value=20,key="num2")

if st.button("Do math"):
    if operation == "add":
        num = num1 + num2
    elif operation == "subtract":
        num = num1 - num2
    elif operation == "multiply":
        num = num1 * num2
    elif operation == "divide":
        num = num1 / num2

    st.write(f"With the operation {operation}, your result is {num}.")

Here’s how you can do it:

import streamlit as st
import random

operation = st.selectbox(
    "Which type of operation shall we do for the numbers 1 and 2?",
    ["add", "subtract", "multiply", "divide"],
)

if "rand_num1" not in st.session_state:
    st.session_state["rand_num1"] = random.randint(0, 20)

if "rand_num2" not in st.session_state:
    st.session_state["rand_num2"] = random.randint(0, 20)

if st.toggle("Randomly generate my numbers"): # I think this looks nicer than a checkbox here
    if st.button("regenerate numbers"):
        st.session_state["rand_num1"] = random.randint(0, 20)
        st.session_state["rand_num2"] = random.randint(0, 20)
    num1 = st.session_state["rand_num1"]
    num2 = st.session_state["rand_num2"]
    st.write(f"Your random numbers are: `{num1}` and `{num2}`.")


else:
    num1 = st.number_input(
        "What is the first number?", min_value=0, max_value=20, key="num1"
    )
    num2 = st.number_input(
        "What is the second number?", min_value=0, max_value=20, key="num2"
    )

if st.button("Do math"):
    if operation == "add":
        num = num1 + num2
    elif operation == "subtract":
        num = num1 - num2
    elif operation == "multiply":
        num = num1 * num2
    elif operation == "divide":
        num = num1 / num2

    st.write(f"With the operation {operation}, your result is {num}.")

Thank you @blackary!! I’d been trying this with callback functions, so I’m not sure I would have gotten there. (Initial reply was due to my incorrect transcription of your code, lesson learned :see_no_evil:)

And FYI for those running an older version of streamlit like me, this does also work with the checkbox widget.

1 Like

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