简体   繁体   中英

WTForms/Flask: Dynamic min_entries

I'm looking to use the min_entries WTForms parameter dynamically ie without hardcoding numbers.

It would look something like this in the form.py:

class TestSpecForm(FlaskForm): 
    student_number = IntegerField('Number of Students')


class StudentForm(FlaskForm):
    answer = StringField('')


class TestInputForm(FlaskForm):
    students = FieldList(FormField(StudentForm))  # I'd like to insert the dynamic min_entries here
    submit = SubmitField('Submit')

and something like this in the views.py:

def input(key_id):
    key = Testspecs.query.get_or_404(key_id) 
    student_number = key.student_number
    form = TestInputForm()
    form.students.min_entries = student_number
    if form.validate_on_submit():
        ...

This, however, does not work and simply renders NO FIELDS for the TestInputForm. If I put "min_entries = 10" into the students variable of the TestInputForm, everything works as expected. But I can't get it done dynamically.

Could anyone help me please? According to all my google/reddit/SO searches, this is basically the way most parameters or validators in WTForms are dynamically set.

Thank you

I just found out about Field Lists and Form Fields, and scoured the internet for documentation or examples and found very little help. I figured out what seems like a good way to get dynamic numbers of entries when you go to render your template, so I figured I'd submit it here in case it helps anyone. Note that this doesn't address adding entries on the fly using a button or anything like that.

def input(key_id):
    key = Testspecs.query.get_or_404(key_id) 
    student_number = key.student_number
    form = TestInputForm()
    # if the form was submitted, then it will collect all the entries for us
    if form.validate_on_submit():
        # form has whatever entries were just submitted
        for entry in form.students.entries:
            ...
        return(redirect(...))
    # if we get here, either validation failed or we're just loading the page
    # we can use append_entry to add up to the total number we want, if necessary
    for i in range(len(form.students.entries), student_number):
        form.students.append_entry()
    return render_template("input.html", form=form)

It isn't possible to override min_entries on a FieldList dynamically.

The workaround is to subclass the form and bind a new FieldList with the desired value.

So your code would have to look something like this:

def input(key_id):
    key = Testspecs.query.get_or_404(key_id) 
    student_number = key.student_number
    # Subclass form and bind new field
    class LocalForm(TestInputForm):pass
    LocalForm.students = FieldList(FormField(StudentForm), min_entries=student_number)
    # Use our new form
    form = LocalForm()
    if form.validate_on_submit():
        ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM