0

If you dynamically add a field to a WTForms form, the newly-added fields are not validated (even if you add validators).

For instance, in Flask:

@app.route('/add', methods=['GET', 'POST'])
def add():
    if 'state' not in session:
        session['state'] = 1

    form = MyForm()

    if request.method == 'POST' and form.validate():
        if session['state'] == 1:
            setattr(
                MyForm,
                'asd',
                StringField(
                    'asdfield',
                    validators = [
                        DataRequired(),
                        Length(min=1)
                    ]
                )
            )
            form = MyForm()
            session['state'] = 2
            return render_template(
                'add.html',
                form=form
            )
        print(len(form.asd.data)) # can equal 0
        session['state'] = 1
        return redirect('/add')
    return render_template(
        'add.html',
        form=form
    )

I believe this is due to the fact that form = MyForm() is run every time you go to /add, so even if session['state'] == 2 you run form.validate() on a default form which does not have the dynamically-added field. Therefore, this field cannot be part of the form validation process.

How can one properly address this behaviour ? If it's not possible, then how can one dynamically add fields to an existing form in such a way that all fields get properly validated upon submission ?

Dreadlockyx
  • 181
  • 1
  • 11

1 Answers1

1

Since you call validate() before adding the field, naturally, you can't validate a field which doesn't exist yet. That said, you don't want to add a field to an instance instead of a class. This is because since WTForms processes its input data at construction, adding fields to the instance is mostly a meaningless thing.

If your field name is static, you can use the del trick detailed here

If it's dynamic, you could instead follow the dynamic form composition pattern from the docs.

Since I've gone over this in detail, I'll link my previous example here: Wtfforms dynamic generation

Crast
  • 15,996
  • 5
  • 45
  • 53
  • I've actually done that beforehand and it did work, but I forgot to add a portion of code to show errors when `session['state']==2` (thus making me believe there was no validation). I should also mention that the dynamic field have to be removed using `delattr` otherwise they will stay forever. – Dreadlockyx Aug 31 '17 at 08:44