尝试创建一个基于列表生成可变数量字段的表单

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(),其中键是子表单中字段的名称,值是字段的对象类型。