我希望使用python / flask / flask-wtf构建一个多项选择测验。我成功地从数据库中提取随机问题,并将随机选择作为可能的答案。我在模板页面上使用for循环,首先显示问题,然后是可能的答案。
这是我的模板。
<div class="quote-block">
{% for quote in quotes %}
{{ quote.line_text }}
<form method="POST">
{{ form.hidden_tag() }}
{{ form.question }}
<input type="submit">
</form>
{% endfor %}
</div>
我的问题是每个问题和相同顺序的可能答案是相同的。我明白为什么会这样。对RadioField选项的数据库查询只发生一次。然后针对for循环的每个实例提取该查询的结果。
这是我的观点路线。
@app.route('/quiz/', methods=['POST', 'GET'])
def quiz():
quotes = Quotes.query.order_by(func.rand()).limit(5)
form = Quiz()
form.question.choices = [(choice.speaker_id, choice.speaker) for choice in Characters.query.order_by(func.rand()).limit(4)]
return render_template('television/quiz.html', form=form, quotes=quotes, options=options)
我的表格。
class Quiz(FlaskForm):
question = RadioField('Label', choices=[])
像我说的那样,所有这些都有效。我无法弄清楚如何为每个问题开始新的选择查询。任何帮助将不胜感激。谢谢!
答案 0 :(得分:0)
您可以尝试动态扩展FlaskForm:
def Quiz(number_of_questions):
class _Quiz(FlaskForm):
pass
for n in range(number_of_questions):
setattr(_Quiz, RadioField('Label', choices=[]), 'question_' + str(n))
return _Quiz()
现在,您的表单每个问题都有一个question_ [n]属性,因此您可以在jijna2中对其进行迭代:
<div class="quote-block">
<form method="POST">
{{ form.hidden_tag() }}
{% for q_num in range(n) %}
{{ quotes[q_num].line_text }}
{{ form['question_' + q_num|string }}
{% endfor %}
<input type="submit">
</form>
</div>
答案 1 :(得分:0)
经过大量的阅读和研究,我意识到我试图过早地做太多事情。因此,我退后一步,建立了我想做的工作的块,然后最终将它们组合在一起。当然,我在表单验证部分遇到了新问题,但是我将其包含在新问题中。
我最大的障碍是我试图为RadioField选择随机选择选项。相反,我在数据库表中添加了三列,并在表中提供了选项。这样一来,通过一个查询即可提取选项和问题。
基本上,我正在表单中的字段上运行一个for循环。如果该字段是RadioField,它将对数据库运行查询并拉出随机行。然后,我在拉出的行上使用另一个for循环,并将不同的元素分配给RadioField的各个部分(标签,选项)。
如果您知道执行此操作的更优雅的方法,我很想听听。但是现在它可以了。
我的表单和模板保持不变。但是,这是我的新路线视图。
@app.route('/quiz/', methods=['GET', 'POST'])
def quiz():
form = Quiz()
for field in form:
if field.type != "RadioField":
continue
else:
pulls = Quotes.query.order_by(func.rand()).limit(1)
for pull in pulls:
answer = pull.speaker
option_two = pull.option_two
option_three = pull.option_three
option_four = pull.option_four
question = pull.line_text
field.label = pull.line_text
field.choices = [(answer, answer), (option_two, option_two), (option_three, option_three), (option_four, option_four)]
return redirect(url_for('you_passed'))
return render_template('television/quiz.html', form=form)