尝试创建一个基于列表生成可变数量字段的表单
Trying to create a form which generates a variable number of fields based on a list
我正在使用 Flask 和 Python 构建一个网络应用程序,它为用户创建一个测验。对于每个主题,我都有一个问题列表(根据主题的不同数量),这些问题是列表中包含的字符串 (question_list
).
我需要创建一个表格,其中 contains/creates 基于相关 question_list
的可变数量 StringFields
- 每个 StringField
问题的标签question_list
。
我已经尝试创建一个基于子表单的 FieldList
,但是为了让它工作,我不得不在子表单中预先定义标签,这并不理想(由于可变数量的字段)。
我也尝试过使用 'setattr' 将新字段附加到静态字段,但这似乎也需要预先定义表单 class 中的字段数。
这是我试过的 FieldList
解决方案:
question_list = [this is a list of questions]
class aQuestion(Form): #child form
question1 = StringField(question_list[0])
question2 = StringField(question_list[1])
question3 = StringField(question_list[2])
class QuestionForm(FlaskForm):
question = FieldList(FormField(aQuestion))
这是我试过的附加解决方案:
class QuestionForm(FlaskForm):
question = StringField('static field')
record = {'field1':'label1', 'field2':'label2'}
for key, value in record.items():
setattr(QuestionForm, key, StringField(value))
没有错误消息 - 但对于解决方案 #1,我必须指定子表单中的所有字段,以及处理可变长度的条件语句。
对于解决方案#2,它似乎只输出两个字段(没有标签),并且不允许可变数字。
已编辑: 我对答案做了一些修改以考虑您的意见。而且这次亲测了,应该是可以的!
您的第一种方法最接近正确答案,但您遗漏了两个关键组成部分:子表单包含的内容太多,并且您没有使用 append_entry()
。
from wtforms.fields import Label
question_list = [this is a list of questions]
class QuestionForm(FlaskForm): #child form
question = StringField()
class AllQuestionsForm(FlaskForm):
questions = FieldList(FormField(QuestionForm))
submit = SubmitField('Submit')
@app.route('/questions/', methods=['GET', 'POST'])
def questions():
form = AllQuestionsForm()
if form.validate_on_submit():
return redirect(url_for('answered'))
for question_str in question_list:
qfield = form.questions.append_entry().question
qfield.label = Label(qfield.id, question_str)
return render_template('questions.html', form=form)
不要忘记在每个子表单的 Jinja for
循环中包含 hidden_tag()
。 (您之前看到的错误是因为子表单不是 FlaskForm,它只是一个直接的表单。FlaskForm includes CSRF protection,因此您应该改用它。)
{% for q in form.questions %}
{{ q.hidden_tag() }}
{{ q.question.label }} {{ q.question() }}
{% endfor %}
{{ form.submit() }}
如果要填充子表单中的字段,可以将字典传递给 append_entry()
,其中键是子表单中字段的名称,值是字段的对象类型。
我正在使用 Flask 和 Python 构建一个网络应用程序,它为用户创建一个测验。对于每个主题,我都有一个问题列表(根据主题的不同数量),这些问题是列表中包含的字符串 (question_list
).
我需要创建一个表格,其中 contains/creates 基于相关 question_list
的可变数量 StringFields
- 每个 StringField
问题的标签question_list
。
我已经尝试创建一个基于子表单的 FieldList
,但是为了让它工作,我不得不在子表单中预先定义标签,这并不理想(由于可变数量的字段)。
我也尝试过使用 'setattr' 将新字段附加到静态字段,但这似乎也需要预先定义表单 class 中的字段数。
这是我试过的 FieldList
解决方案:
question_list = [this is a list of questions]
class aQuestion(Form): #child form
question1 = StringField(question_list[0])
question2 = StringField(question_list[1])
question3 = StringField(question_list[2])
class QuestionForm(FlaskForm):
question = FieldList(FormField(aQuestion))
这是我试过的附加解决方案:
class QuestionForm(FlaskForm):
question = StringField('static field')
record = {'field1':'label1', 'field2':'label2'}
for key, value in record.items():
setattr(QuestionForm, key, StringField(value))
没有错误消息 - 但对于解决方案 #1,我必须指定子表单中的所有字段,以及处理可变长度的条件语句。
对于解决方案#2,它似乎只输出两个字段(没有标签),并且不允许可变数字。
已编辑: 我对答案做了一些修改以考虑您的意见。而且这次亲测了,应该是可以的!
您的第一种方法最接近正确答案,但您遗漏了两个关键组成部分:子表单包含的内容太多,并且您没有使用 append_entry()
。
from wtforms.fields import Label
question_list = [this is a list of questions]
class QuestionForm(FlaskForm): #child form
question = StringField()
class AllQuestionsForm(FlaskForm):
questions = FieldList(FormField(QuestionForm))
submit = SubmitField('Submit')
@app.route('/questions/', methods=['GET', 'POST'])
def questions():
form = AllQuestionsForm()
if form.validate_on_submit():
return redirect(url_for('answered'))
for question_str in question_list:
qfield = form.questions.append_entry().question
qfield.label = Label(qfield.id, question_str)
return render_template('questions.html', form=form)
不要忘记在每个子表单的 Jinja for
循环中包含 hidden_tag()
。 (您之前看到的错误是因为子表单不是 FlaskForm,它只是一个直接的表单。FlaskForm includes CSRF protection,因此您应该改用它。)
{% for q in form.questions %}
{{ q.hidden_tag() }}
{{ q.question.label }} {{ q.question() }}
{% endfor %}
{{ form.submit() }}
如果要填充子表单中的字段,可以将字典传递给 append_entry()
,其中键是子表单中字段的名称,值是字段的对象类型。