validate_on_submit() 在动态生成 RadioButton 选项时失败
validate_on_submit() fails when RadioButton choices are dynamically generated
我正在创建类似测验的网络应用程序,用于使用 Flask、Jinja、WTForms、SqlAlchemy 等学习语言。一旦用户通过成功完成存储在 JSON 文件中的所有级别完成此类语言课程,我想要该应用程序为他提供了一个练习模式,用户将在其中回答随机选择的级别。
当我 运行 应用程序时,我可以根据需要看到使用随机级别的值生成的单选按钮,但是当我选择任何答案并提交时,form.validate_on_submit () returns False and form.errors returns {'practiceform': [u'Not a valid choice']}.当我将值硬编码到 currentLevel 变量时,它可以正常工作。
views.py
@user_blueprint.route('/courses/<course>/quiz/practice',methods=['GET','POST'])
@login_required
def practice(course):
courseClass = class_for_name("project.models", course.capitalize())
courses = courseClass.query.filter_by(email=current_user.email).first()
maxLevel = courseClass.query.filter_by(email=current_user.email).first().get_maxLevel()
currentLevel = randint(0, maxLevel-1) # If this value is hard-coded or fetched from db, it works correctly
dic = generateQuestion(course, currentLevel)
display = dic["display"]
correct = dic["correct"]
options = dic["options"]
form = PracticeForm(request.form)
form.practiceform.choices = [(option, option) for option in options]
if form.validate_on_submit():
practiceForm = form.practiceform.data
if ((practiceForm == correct) and courses):
# Do something
flash("Nice job", 'success')
return redirect(url_for('user.practice', course=course))
else:
# Do something else
flash("Wrong answer", 'danger')
return redirect(url_for('user.practice', course=course))
return render_template('courses/practice.html', form=form, display=display)
forms.py
class PracticeForm(Form):
practiceform = RadioField('practice')
practice.html
{% extends "_base.html" %}
{% block content %}
<form action='' method='POST' role='form'>
<p>
<!-- Tried put form.csrf, form.csrf_token, form.hidden_tag() here -->
{{ form.practiceform() }}
</p>
<input type="submit" value="submit" />
</form>
{% endblock %}
那我错过了什么?让我们说硬编码级别 25 之间有什么区别,它可以正常工作,或者如果数字 25 是在 randint 中随机生成的?
我的猜测是 option
是一个 int
,错误 WTForms 从 request.form
得到一个 str
。
当数据从请求中返回时,它被 WTForms 视为 string
,除非您使用 wtforms.fields.*Field
构造函数的 coerce
kwarg 明确指定类型:
practiceform = RadioField('practice', coerce=int)
所以我发现问题是 randint() 引起的,因为在 GET 和 POST 操作上都调用了 practice(course) 方法,这导致有两个不同的整数 -> 大多数时候是两种不同的形式.所以我重构了代码。保留 GET 操作的实践(课程)方法并创建一个处理 POST 操作的新方法,这解决了问题。
我正在创建类似测验的网络应用程序,用于使用 Flask、Jinja、WTForms、SqlAlchemy 等学习语言。一旦用户通过成功完成存储在 JSON 文件中的所有级别完成此类语言课程,我想要该应用程序为他提供了一个练习模式,用户将在其中回答随机选择的级别。
当我 运行 应用程序时,我可以根据需要看到使用随机级别的值生成的单选按钮,但是当我选择任何答案并提交时,form.validate_on_submit () returns False and form.errors returns {'practiceform': [u'Not a valid choice']}.当我将值硬编码到 currentLevel 变量时,它可以正常工作。
views.py
@user_blueprint.route('/courses/<course>/quiz/practice',methods=['GET','POST'])
@login_required
def practice(course):
courseClass = class_for_name("project.models", course.capitalize())
courses = courseClass.query.filter_by(email=current_user.email).first()
maxLevel = courseClass.query.filter_by(email=current_user.email).first().get_maxLevel()
currentLevel = randint(0, maxLevel-1) # If this value is hard-coded or fetched from db, it works correctly
dic = generateQuestion(course, currentLevel)
display = dic["display"]
correct = dic["correct"]
options = dic["options"]
form = PracticeForm(request.form)
form.practiceform.choices = [(option, option) for option in options]
if form.validate_on_submit():
practiceForm = form.practiceform.data
if ((practiceForm == correct) and courses):
# Do something
flash("Nice job", 'success')
return redirect(url_for('user.practice', course=course))
else:
# Do something else
flash("Wrong answer", 'danger')
return redirect(url_for('user.practice', course=course))
return render_template('courses/practice.html', form=form, display=display)
forms.py
class PracticeForm(Form):
practiceform = RadioField('practice')
practice.html
{% extends "_base.html" %}
{% block content %}
<form action='' method='POST' role='form'>
<p>
<!-- Tried put form.csrf, form.csrf_token, form.hidden_tag() here -->
{{ form.practiceform() }}
</p>
<input type="submit" value="submit" />
</form>
{% endblock %}
那我错过了什么?让我们说硬编码级别 25 之间有什么区别,它可以正常工作,或者如果数字 25 是在 randint 中随机生成的?
我的猜测是 option
是一个 int
,错误 WTForms 从 request.form
得到一个 str
。
当数据从请求中返回时,它被 WTForms 视为 string
,除非您使用 wtforms.fields.*Field
构造函数的 coerce
kwarg 明确指定类型:
practiceform = RadioField('practice', coerce=int)
所以我发现问题是 randint() 引起的,因为在 GET 和 POST 操作上都调用了 practice(course) 方法,这导致有两个不同的整数 -> 大多数时候是两种不同的形式.所以我重构了代码。保留 GET 操作的实践(课程)方法并创建一个处理 POST 操作的新方法,这解决了问题。