I am working on to display Movie recommendations; I am able to display 10 movies when a user input from st.selectbox and click on “Show Recommendation” Button.
I am also able to get the button on caption of each movie but when i click on the button for one of the movies, it is not calling the function again.
It is going to the first page of “Show Recommendation” with st.selectbox showing the movie name for which i got the 10 movies.
When user click on the movie it shld display the next 10 movie related to that movie.
Steps to reproduce
Code snippet:
if st.button('Show Recommendations'):
movie_name(selected_movie_name)
def movie_name(selected_movie_name)
with col1:
# st.text(recommended_movies[0])
st.image(recommended_movie_posters[0])
selected_movie_name=recommended_movies[0]
button=st.button(recommended_movies[0])
if button:
movie_name(selected_movie_name)
Buttons don’t have a persistent state. They will return True immediately after clicking them, but go back to False if the user interacts with anything else. So upon clicking a button within your movie_name function, your page will reload with st.button('Show Recommendations') being false and it will look like the first page load.
You can either use a checkbox so that there is some retained state, or you can use session state to keep a memory of your button clicks.
Here’s an example creating some memory for the outer button. You can do the same for more nested buttons as needed.
# Initialize some state for showing recommendations
if 'show_recommendation' not in st.session_state:
st.session_state.show_recommendation = False
# Callback function to make sure the state changes with each button click
def change_show():
st.session_state.show_recommendation = not st.session_state.show_recommendation
# Independent button, with attached callback function
st.button('Show Recommendations', on_click=change_show)
# Conditional called on the key stored in session state instead of directly on the button value
if st.session_state.show_recommendation:
st.write('Movie recommendations showing here')
st.button('Another button here')
If you want any persistence with the effect of a button, make sure you are not passing the button directly into your conditional. The point of the callback function is to store information in session state that will survive past what the button remembers. You want to base your conditionals on that session state information.
So instead of:
Set the button outside of the conditional with the callback to record info in session state, then set your conditional on that session state value:
st.button(‘Show Recommendations’, on_click=set_stage, args=(1,))
if st.session_state.stage > 0:
recommended_movies=movie_name(selected_movie_name)
Thanks!!!
But now…it is trying to display both from “first button and then second button” because of which it is throwing key error " DuplicateWidgetID : There are multiple identical st.button widgets with key='11' ."
Initially is should show first 10 movies…then if I click on one of the movies…the first 10 should clear up and then next 10 corresponding to the movie I clicked should show up.
Thanks for the help!!!
def set_stage(stage):
st.session_state.stage = stage
global movie1
if “stage” not in st.session_state:
st.session_state.stage = 0
If you use the code blocking to preserve white space, it will be a bit easier to parse what your code says. Like this:
def my_func():
st.write('Hello')
If you have code that is going to generate a button (or any widget) within a loop, you will need to manually assign a unique key to that widget so there is no conflict.
for movie in movie_list:
st.button('Show', key=movie)
If you have multiple widgets being created per movie, expand the string used for the key so that it is truly unique across all widgets within all loops, etc.
I’m a little unclear here. Do you have your full script in a repository you could link? Or could you show a bit more of where you are right now in code?
Ok, I see what you tried to do. Assuming you want the “Show Recommendations” button to present the 10 movies, then from there click any of the movies button shows some additional information for that movie:
You would probably be best served having two distinct keys in session state to separate the concepts of “where you are in the process” and “what option among many was selected.” I don’t know if you have any further buttons beyond the two steps shown, but you can create a different key to register the last button clicked among the recommendations. If you need to nest more layers of buttons, you can adjust callback functions to update the stage key also.
You can condense down where you are listing out the 10 recommendations with their buttons like this:
# New callback for the individual movie buttons
def selected(i):
st.session_state.selected = i
# initialize a new key
if 'selected' not in st.session_state:
st.session_state.selected = None
# get your columns as a list so it's easier to increment through them
columns = st.columns(5)
# increment through your 10 items in the list, by index
for i in range(10):
# increment through your columns by index, using mod 5 to loop through 0 to 4, twice
with columns[i%5]:
# st.text(recommended_movies[i])
st.image(recommended_movie_posters[i])
# now the individual movie buttons affect the 'selected' key instead of the 'stage' key
st.button(recommended_movies[i], on_click=selected, args=(i,), key=recommended_movies[i])
if st.session_state.selected is not None:
i = st.session_state.selected
st.write(recommended_movies[i])
movie_name(recommended_movies[i])
If you need each movie button to work like an on/off switch and potentially show more than one secondary result at once, that’s possible too but would have a different structure to save more than a single index number at a time.
You can append an extra digit or string to your widget keys representing the tier they are displayed in to keep the keys unique. For example, the first 10 would have recommended_movies[i]+'first' as the key and when you are showing them in the next tier, you would use recommended_movies[i]+'second'. But if you are going to nest these expansions of 10 movies at a time further, you will either need additional keys or you’ll need to make your “selection” a list so it can keep track of a series of selections.
You can create buttons with new callback functions to reset whichever keys you want for your process.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.