Reputation: 889
Using WTForms
, I ask the user to enter two numbers that will be further used on a simple calculation. Those numbers both need to be validated.
I have defined the following form
class AForm(Form):
ff=DecimalField(default=0.0, validators=[NumberRange(min=0, max=2)])
The template
<form action="/test" method=post>
{% for L in entries %}
{{ render_field(form.ff) }}
{% endfor %}
<input class="button" type="submit" value="calc">
</form>
The Flask view
@app.route('/test', methods=['GET', 'POST'])
def get_form():
entries=[0, 1]
form = AForm(request.form)
ff_l=request.form.getlist('ff')
if request.method == 'POST' and form.validate():
L=0
v=0
a=0
b=0
for L,v in enumerate(ff_l):
a=float(v)
b+=a
return render_template('res.html', b=b)
return render_template('test.html', entries=entries, form=form)
I am aware I am using the getlist
method, which is not part of WTForms
, but this is the only solution found so far, since, by doing ff_l=form.ff.data
, I would get a dict
with only one value per field and not the whole list, associated to the given field.
Problems start when I want to validate submitted values: the form.validate()
method will only validate the first value of the list, while the second will not be subjected to any validation.
My question: how is it possible to validate each value of a list ?
Thanks in advance !
Upvotes: 4
Views: 3424
Reputation: 159905
You will want to use FieldList
to let WTForms know there can be more than one entry:
field = DecimalField(default=0.0, validators=[NumberRange(min=0, max=2)])
class AForm(Form):
ff = FieldList(field)
Then you should be able to simply set the data in the form constructor:
@app.route('/test', methods=['GET', 'POST'])
def get_form():
entries=[0, 1]
form = AForm(request.form, ff=entries)
ff_l = form.ff.data
if request.method == 'POST' and form.validate():
result = sum(ff_l)
return render_template('res.html', b=result)
return render_template('test.html', form=form)
And your template should now loop over the subfields in form.ff
:
<form action="/test" method=post>
{% for field in form.ff %}
{{ render_field(field) }}
{% endfor %}
<input class="button" type="submit" value="calc">
</form>
Upvotes: 4