Почему WTForms имеют несвязанные поля при первой загрузке страницы? - PullRequest
0 голосов
/ 26 марта 2019

У меня есть следующие классы форм:

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 голосов
/ 26 марта 2019

Хотя я до сих пор не знаю, почему оригинальная функция не работала при первой загрузке страницы, а работала при перезагрузке, я пошел по этому поводу другим путем и решил проблему. Вместо того чтобы устанавливать поля в __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()
    ...
...