I keep getting the error: "DuplicateWidgetID: There are multiple widgets with the same key='submit_answer'."
I am trying to loop through the questions however it looks like it's still pulling all sessions states at the same time. Which then throws the duplicate widget error.
So I was curious what should be changed with the session state code so that it would iterate through better? Or open for any other recommendations. I am trying to create a game of yes/no questions. Where you could answer one question at at time and it tell you if you were right or wrong. And then also give a total score at the end.
import streamlit as st
import pandas as pd
def main():
st.title('Employer Test') # Check if 'started' key exists in session_state, if not, display candidate information
if not st.session_state.get('started'):
st.markdown('## Candidate Information')
# Full Name Input
full_name = st.text_input('Full Name')
# Experience Dropdown
experience = st.selectbox("Experience", [" Showcase"], index=0)
# Language Dropdown
language = st.selectbox("Type of Game", [" Game"], index=0)
# Button to start the test
if st.button('Submit'):
if full_name:
st.session_state['started'] = True
st.session_state['full_name'] = full_name
run_python_test()
else:
run_python_test()
def run_python_test():
st.title('Is the follow statement or question related to XYZ')
# Dummy test questions and answers
questions = [
{ 'question': 'Question 1',
'options': ['Yes', 'No'],
'correct_answer': 'Yes'
},
{
'question': 'Question 2',
'options': ['Yes', 'No'],
'correct_answer': 'No'
},
{
'question': 'Question 3',
'options': ['Yes', 'No'],
'correct_answer': 'Yes'
}
# Add more questions here...
]
total_questions = len(questions)
if 'answer' not in st.session_state:
st.session_state['answer'] = [''] * total_questions
for i, question_data in enumerate(questions):
question = question_data['question']
st.write(f'Question {i+1}: {question}')
# Display options for each question
st.session_state['answer'][i] = st.text_area(f"Enter answer for Question {i+1}", value=st.session_state['answer'][i], key=f"answer_{i}")
# Add a submit button
if st.button("Submit Test", key="submit_answer"):
score = 0
# Process the answers and calculate score
for i, ans in enumerate(st.session_state['answer']):
if ans == questions[i]['correct_answer']:
score += 1
st.write(f"Question {i+1} Answer: {ans}")
percentage_score = (score / total_questions) * 100
if percentage_score >= 60:
save_result(st.session_state['full_name'], percentage_score)
st.session_state['test_completed'] = True
def save_result(full_name, score):
data = {'Full Name':[full_name], 'Score':[score]}
df = pd.DataFrame(data)
df.to_csv('test_results.csv',index=False)
st.write('Result saved')
if __name__ == '__main__':
main()
Streamlit st.session_state
behaves like a dictionary, so that you can have only unique identifiers as keys. Moreover, each widget created with an explicit key is added to the state.
That said, your issue is that you are creating a submit button with the same key for each question. If you want to create a button for each question, you need to give unique identifiers to them, just like:
for i, question_data in enumerate(questions):
# ...
if st.button("Submit Test", key=f"submit_answer_{i}"):
# ...
Otherwise, you can reconfigure you app to maybe use st.form and st.form_submit_button.