Open figoyouwei opened 1 month ago
Please focus on this issue today, thanks.
The warning is triggered because choice_adapter
receives a string object:
A: Please ask a question with Score: 0
of type <class 'str'>Then choice_adapter
tries to print cho.symbol
, which fails because cho
is a string.
You can avoid the warning by preventing choice_adapter
from dealing with non-Choice
inputs:
def choice_adapter(cho: Choice):
if type(cho) is Choice:
print(cho.symbol)
choice_text = "{}: {}".format(cho.symbol, cho.text)
return (cho.symbol_no, choice_text)
else:
return None
To get the content of all selectors, my solution is a bit convoluted as we did not expect people to generate selectors this way. I will discuss R&D to make this simpler in the future. Here is a solution that works:
When I select the second answer and then the first answer and press the "Submit" button:
The console prints state.answers
with value ['2', '1']
Here is the full code:
import os
import django
# Set up Django environment
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "questionnaire.settings")
django.setup()
from questions.models import Question
from questions.models import Choice
# Fetch the questions and choices
Fragen = Question.objects.all()[0:2]
Choices = Fragen
selected_choice = Choice()
def choice_adapter(cho: Choice):
if type(cho) is Choice:
choice_text = "{}: {}".format(cho.symbol, cho.text)
return (cho.symbol_no, choice_text)
else:
return None
answers = [""] * len(Fragen)
def get_selected(state, var_name, value):
index = int(var_name[10:])
state.answers[index] = value
state.answers = state.answers
def submit(state):
print(state.answers)
# Create the questionnaire page with Taipy GUI Builder (TGB)
from taipy.gui import Gui
import taipy.gui.builder as tgb
# Use Taipy GUI Builder (TGB) to display all questions and choices
with tgb.Page() as page:
# Title and Theme Toggle
tgb.toggle(theme=True)
tgb.text("### Taipy Questionnaire", mode="md", class_name="text-center pb1")
# Loop through all questions and their corresponding choices
with tgb.layout(columns="1 2 1", class_name="text-center"):
with tgb.part():
tgb.text(f"", mode="md")
with tgb.part(class_name="text-left"):
# Loop through all questions using enumerate and display them dynamically
for i, frage in enumerate(Fragen):
# Display the question text
tgb.text(f"#### {frage.text}", mode="md")
exec(f"selection_{i} = ''")
# Display selector for each question's choices
tgb.selector(
value="{selection_" + str(i) + "}",
lov=frage.get_choices(), # Get the choices for each question
type=Choice,
adapter=choice_adapter,
on_change=get_selected, # Callback for when the selection changes
)
# Submit button
tgb.button(label="Submit", class_name="mt2", on_action=submit)
with tgb.part():
tgb.text(f"Score", mode="md")
# ------------------------------
# Main app
# ------------------------------
if __name__ == "__main__":
print("Starting Questionnaire app...")
# Initialize and run the GUI
gui = Gui(page)
gui.run()
Actually, here is a more elegant solution that does not use exec
:
When the user selects something, it prints:
Getting selected items
What country do you like most?
Selected: 3
Which city do you like most?
Selected: 1
Here is the code:
import os
import django
# Set up Django environment
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "questionnaire.settings")
django.setup()
from questions.models import Question
from questions.models import Choice
# Fetch the questions and choices
Fragen = Question.objects.all()[0:2]
Choices = Fragen
selected_choice = Choice()
def choice_adapter(cho: Choice):
if type(cho) is Choice:
choice_text = "{}: {}".format(cho.symbol, cho.text)
return (cho.symbol_no, choice_text)
else:
return None
def get_selected(state):
print("Getting selected items")
for i, frage in enumerate(Fragen):
print(frage.text)
print(f"Selected: {answers[f'frage_{i}']}")
answers = {}
for i, frage in enumerate(Fragen):
answers[f"frage_{i}"] = ""
# Create the questionnaire page with Taipy GUI Builder (TGB)
from taipy.gui import Gui
import taipy.gui.builder as tgb
# Use Taipy GUI Builder (TGB) to display all questions and choices
with tgb.Page() as page:
# Title and Theme Toggle
tgb.toggle(theme=True)
tgb.text("### Taipy Questionnaire", mode="md", class_name="text-center pb1")
# Loop through all questions and their corresponding choices
with tgb.layout(columns="1 2 1", class_name="text-center"):
with tgb.part():
tgb.text(f"", mode="md")
with tgb.part(class_name="text-left"):
# Loop through all questions using enumerate and display them dynamically
for i, frage in enumerate(Fragen):
# Display the question text
tgb.text(f"#### {frage.text}", mode="md")
# Display selector for each question's choices
tgb.selector(
value="{answers.frage_" + str(i) + "}",
lov=frage.get_choices(), # Get the choices for each question
type=Choice,
adapter=choice_adapter,
on_change=get_selected, # Callback for when the selection changes
)
# Submit button
tgb.button(
label="Submit",
class_name="mt2",
)
with tgb.part():
tgb.text(f"Score", mode="md")
# ------------------------------
# Main app
# ------------------------------
if __name__ == "__main__":
print("Starting Questionnaire app...")
# Initialize and run the GUI
gui = Gui(page)
gui.run()
That was elegant.
selector returned more than one Choice. The code is updated and the video in a separate email, please focus on this issue, thanks. https://github.com/figoyouwei/taipy_success/blob/main/littlegiant/questionnaire/app.py
Could I expect an update on this Issue?
I found the issue:
The choices: B: Tokyo with Score: 2
and C: Shanghai with Score: 0
have the same symbol_no
(cho.symbol_no
) equals to 2
When you select one of the two, the choice_adapter
will tell Taipy that you selected their cho.symbol_no
. Since they both have the same symbol_no
, it will select both of them.
Either ensure that all choices for the same question have different symbol_no
in the dataset or change choice_adapter
so that it does not use symbol_no
as a key to identify the choice.
ok, thanks, it is running fine now. Just one technical question which I found contradicting to my previous selector experience:
You see, in this code, the value returns ChatSession instance as defined in the tgb.selector.type
tgb.text("### Previous activities", mode="md", class_name="h5 mt2 mb-half")
tgb.selector(
value="{selected_session}",
lov="{sessions}",
on_change=select_session,
# NOTE: displayed text of selector item
type=ChatSession,
adapter=selector_adapter,
# NOTE: css identifier
id="past_prompts_list",
class_name="past_prompts_list",
)
but in the questionnaire code, why the value didn't return a Choice instance as define in type?
with tgb.part(class_name="text-left"):
# Loop through all questions using enumerate and display them dynamically
for i, frage in enumerate(Fragen):
# Display the question text
tgb.text(f"#### {frage.text}", mode="md")
# Display selector for each question's choices
# NOTE: Difference between Django data model and Pydantic
tgb.selector(
value="{selected_choices.frage_" + str(i) + "}",
lov=frage.get_choices(), # Get the choices for each question
type=Choice,
adapter=choice_adapter,
on_change=get_selected, # Callback for when the selection changes
)
From what I understand, we use "type" to understand the "lov" when it is ambiguous. "type" does not define which value will be used, the "adapter" defines which value will be chosen
Hi,
I need some help with this code which runs multiple selector in a Django questionnaire context. https://github.com/figoyouwei/taipy_success/blob/main/littlegiant/questionnaire/app.py
First, when running this app.py, it returns a warning, could it be solved?
More importantly, how do I get the content from this multiple selectors? The page looks like this: