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

时间:2019-03-26 00:07:03

标签: flask-wtforms wtforms

我有以下表单类:

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>

两个页面加载之间的程序状态没有其他区别。

这是什么原因造成的,怎么解决?

1 个答案:

答案 0 :(得分: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()
    ...