My point is the following :
I have a FieldList input with FloatFields on it. But the validators in those nested fields doesn't run.
The NumberRange works fine when I have a basic form.
But when I have a nested form, the wtforms.validators.NumberRange triggers the following error :
TypeError: '<' not supported between instances of 'FloatField' and 'int'
I don't know why does that errors occurs ?
Here is my main file :
from flask import Flask, render_template, flash
from flask_wtf import FlaskForm
from wtforms import FloatField, SubmitField, StringField, FieldList, FormField
from wtforms.validators import NumberRange
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
class mySubForm(FlaskForm):
class Meta:
csrf = False
mySubField = FloatField(validators=[NumberRange(min=-100, max=100)])
class myForm(FlaskForm):
myField = FieldList(FormField(mySubForm))
mySubmit = SubmitField("Save")
@app.route('/', methods=['GET','POST'])
def home():
form = myForm()
xLabels = ["A", "B", "C", "D"]
for x in xLabels:
subForm = mySubForm()
form.myField.append_entry(subForm)
if form.validate_on_submit():
flash("success")
return render_template("draft.html", form=form)
if __name__ == "__main__":
app.run(host="127.0.0.1", port="5000" ,debug=True)
Here is my template :
<!DOCTYPE html>
<html>
<head>
<style>
.error{border-color: red;}
</style>
</head>
<body>
<div>
<form method="POST" action="/">
{{ form.hidden_tag() }}
{% for field in form.myField %}
{% if field.mySubField.errors %}
{{ field.mySubField(class="error") }}
{% for error in field.mySubField.errors %}
<span>{{ error }}</span>
{% endfor %}
{% else %}
{{ field.mySubField.data }}
{% endif %}
{% endfor %}
{{ form.mySubmit() }}
</form>
{% with messages = get_flashed_messages(with_categories=False) %}
{% if messages %}
{% for message in messages %}
<p>{{ message }}</p>
{% endfor %}
{% endif %}
{% endwith %}
</div>
</body>
</html>
The problem is that append_entry doesn't accept a field, it accepts raw data, so the validation fails because it's comparing a number to a FloatField.
Passing it a field is also why you're having to use mySubField.data in the template instead of simply mySubField(), because as it is, mySubField is rendering yet another field, the one you passed it.
To fix it, you can do something like
form.myField.append_entry({'mySubField': some_number})
Which, as mentioned above, would allow you to fix the template too:
{% else %}
{{ field.mySubField() }}
{% endif %}
As an aside, you might want to encase the add_entry logic in a conditional so it only happens in GET requests, otherwise you'll be adding new entries every time you submit the form.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With