为什么WTForms在第一次加载页面时有未绑定的字段?

问题描述 投票:0回答:1

我有以下表单类:

class FieldsRequiredForm(FlaskForm):
    class Meta:
        def render_field(self, field, render_kw):
            render_kw.setdefault('required', True)
            return super().render_field(field, render_kw)


class SingleStringFieldForm(FieldsRequiredForm):
    def __init__(self, field_label=None, question_id=None,
                 submit_label='Submit'):
        super().__init__()
        SingleStringFieldForm.answer = StringField(field_label)
        SingleStringFieldForm.question_id = HiddenField(default=question_id)
        SingleStringFieldForm.submit = SubmitField(submit_label)


class SingleRadioFieldForm(FieldsRequiredForm):
    def __init__(self, field_label=None, question_id=None,
                 submit_label='Submit', choices=None):
        super().__init__()
        SingleRadioFieldForm.answer = RadioField(field_label, choices=choices)
        SingleRadioFieldForm.question_id = HiddenField(default=question_id)
        SingleRadioFieldForm.submit = SubmitField(submit_label)

使用这些表单的函数如下所示:

@bp.route('/survey/<string:slug>', methods=['GET', 'POST'])
def question(slug):
    survey = Survey.query.filter_by(slug=slug).first_or_404()
    questions = survey.questions
    question_ids = [question.id for question in questions]
    if 'answers' not in session:
        session['answers'] = json.dumps({id: None for id in question_ids})
    answers = json.loads(session['answers'])
    if request.method == 'POST':
        record_submitted_answer()
        answers = json.loads(session['answers'])
    if None in answers.values():
        question = get_next_question()
        if question.category == 'word':
            form = SingleStringFieldForm(field_label=question.question,
                                         question_id=question.id)
        elif question.category == 'likert':
            form = SingleRadioFieldForm(field_label=question.question,
                                        question_id=question.id,
                                        choices=tuple(likert().items()))
    else:
        form = SingleStringFieldForm()
    if form.validate_on_submit():
        if None not in answers.values():
            write_answers_to_database(survey=survey)
            with open('app/static/ty.txt', 'r') as f:
                ty = [x.strip() for x in f.readlines()]
            return render_template('ty.html', ty=ty)
        return redirect(url_for('survey.question', slug=slug))
    return render_template('survey.html', form=form, answers=answers)

清除会话后第一次加载页面时,表单没有显示,当我在调试器中单步调试时,调试器会报告form.answer的值为:

<UnboundField(RadioField, ('Question 1',), {'choices': (('1', 'Strongly Agree'),
('2', 'Agree'), ('3', 'Neutral'), ('4', 'Disagree'), ('5', 'Strongly Disagree'))})>

如果我重新加载页面,它有这个值:

<app.survey.forms.SingleRadioFieldForm object at 0x110788d30>

我没有注意到两个页面加载之间的程序状态有什么不同。

第一次造成这种情况的原因是什么?如何解决?

flask-wtforms wtforms
1个回答
0
投票

虽然我仍然不知道为什么原始函数没有在第一页加载时工作,但在重新加载时,我以另一种方式解决了这个并解决了问题。我没有在__init__中设置字段,而是在函数中进行了子类化并直接编辑了类。

@bp.route('/survey/<string:slug>', methods=['GET', 'POST'])
def survey(slug):
    class F(FieldsRequiredForm):
        pass

    ...
    if None in answers.values():
        question = get_next_question()
        F.question_id = HiddenField(default=question.id)
        if question.category == 'word':
            F.answer = StringField(question.question)
        elif question.category == 'likert':
            F.answer = RadioField(question.question, choices=tuple(likert().items()))
        F.submit = SubmitField('Submit')
    else:
        F.answer = StringField()
    form = F()
    ...
© www.soinside.com 2019 - 2024. All rights reserved.