Создание нескольких элементов ввода с использованием одного класса в WTForms (Flask)

#python #python-3.x #flask #flask-wtforms #wtforms

#python #python-3.x #flask #flask-wtforms #wtforms

Вопрос:

Я создаю веб-приложение в Flask для генерации XML для импорта в Excel. Веб-приложение имеет форму, в которой есть 15 вопросов, 4 варианта вопросов, правильный ответ и таймер.

Вот мой forms.py , который использует WTForms:

 from flask_wtf import FlaskForm
from wtforms import StringField, SelectField, IntegerField, SubmitField
from wtforms.validators import DataRequired, Length

class XMLQuestionForm(FlaskForm):
    question = StringField('Question', validators=[DataRequired(), Length(max=395)])
    optionA = StringField('Option A', validators=[DataRequired(), Length(max=85)])
    optionB = StringField('Option B', validators=[DataRequired(), Length(max=85)])
    optionC = StringField('Option C', validators=[DataRequired(), Length(max=85)])
    optionD = StringField('Option D', validators=[DataRequired(), Length(max=85)])
    answer = SelectField('Answer', validators=[DataRequired()], choices=[('Option A','Option B','Option C','Option D')])
    timer = IntegerField('Timer', default=60)
  

Теперь я хочу создать HTML-файл, в котором можно ввести и отправить 15 различных вопросов, вариантов и ответов для каждого из них. После отправки я обработаю это в routes.py

Вот мой routes.py :

 from flask import render_template, url_for, flash, redirect
from myflaskapp import app

@app.route("/")
@app.route("/home",)
def home():
    form = XMLQuestionForm()
    if form.validate_on_submit():
        #Do something
    else:
        flash('ERROR MESSAGE', 'danger')
    return render_template('home.html', title='Questions XML Form', form=form)
  

Я хочу иметь 15 таких полей, как я упоминал выше, без необходимости создавать несколько переменных класса формы.

Как мне это сделать?

Ответ №1:

Я оставлю за собой право судить об эффективности или целесообразности этого подхода, но один из способов сделать это — использовать фабричную функцию:

 def create_form(input):
    class Form(FlaskForm):
        timer = IntegerField('Timer', default=60)

    kwargs = {'validators': [DataRequired(), Length(max=85)]}
    for i, vals in enumerate(input):
        setattr(Form, 'questn_'   str(i), StringField(vals[0], **kwargs))
        setattr(Form, 'answer_'   str(i), StringField(vals[1], **kwargs))
        for j, opt in enumerate(vals[2]):
            setattr(Form, 'opt_'   str(i)   str(j), StringField(opt, **kwargs))
    
    return Form

Form = create_form([
    ['Question1', 'Answer1', ['OptA', 'OptB', 'OptC']],
    ['Question2', 'Answer2', ['OptX', 'OptY']]
])