Reputation: 181
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 ?
Upvotes: 0
Views: 589
Reputation: 16316
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
Upvotes: 1