简体   繁体   English

Flask-WTF 未使用 FieldList 子表单进行验证

[英]Flask-WTF not validating with FieldList subforms

I am trying to get a test form that includes subforms to work but the form does not validate on submission.我正在尝试获取一个包含子表单的测试表单,但该表单在提交时未验证。 The form itself is submitting a recipe with ingredients as its subforms using FieldList() .表单本身正在使用FieldList()提交包含成分的食谱作为其子表单。 I have also made sure to include hidden_tag() in the HTML.我还确保在 HTML 中包含hidden_tag()

Forms:形式:

class IngredientsForm(FlaskForm):
    ingredient_name = StringField("Ingredient", validators=[DataRequired()])


class RecipeForm(FlaskForm):
    recipe_name = StringField("Recipe name", validators=[DataRequired()])
    ingredients = FieldList(FormField(IngredientsForm), min_entries=2, max_entries=5)
    submit = SubmitField("Submit")

Views:意见:

@app.route("/", methods=["GET", "POST"])
def index():
    form = RecipeForm()
    return render_template("index.html", form=form)


@app.route("/submit", methods=["POST"])
def submit():
    form = RecipeForm()
    print(f"ERRORS: {form.errors}")
    print(f"DATA: {form.data}")
    if form.validate_on_submit():
        print("Validated!")
        print(form.recipe_name)
        for ingredient in form.ingredients.data:
            print(ingredient)
        return redirect("/")
    else:
        print("Form not validated")
    return render_template("index.html", form=form)

HTML: HTML:

<h1>Enter recipe:</h1>
<form action="/submit" method="POST">
    {{ form.hidden_tag() }}
    <p>
        {{ form.recipe_name.label }} <br>
        {{ form.recipe_name() }}
    </p>
    <p>
        {{ form.ingredients.label }} <br>
        {% for ing in form.ingredients %}
            {{ ing.ingredient_name.label }}
            {{ ing.ingredient_name() }}
            <br>
        {% endfor %}
    </p>
    <p>
        {{ form.submit() }}
    </p>
</form>

Output:输出:

ERRORS: {}
DATA: {'recipe_name': 'butterbread', 'ingredients': [{'ingredient_name': 'butter', 'csrf_token': None}, {'ingredient_name': 'bread', 'csrf_token': None}], 'submit': True, 'csrf_token': 'Ijg1NmVjZjIwODY3MTJkNDNkMTFiNDQ2YzdiNzYyYzYyNmUzNGUzMWMi.YtaF7g.WRn25PWYMFplr_KV7RoZq1uLgrI'}
Form not validated
127.0.0.1 - - [19/Jul/2022 03:22:44] "POST /submit HTTP/1.1" 200 -

So far, no errors show up but it looks like in the data that since each subform has None as its csrf_token, maybe that's messing up the validation?到目前为止,没有出现任何错误,但看起来在数据中,因为每个子表单都有None作为它的 csrf_token,也许这会弄乱验证? I've tried getting this to validate for a while but to no avail.我试过让这个验证一段时间,但无济于事。

Figured it out.弄清楚了。 The problem is that the subform IngredientsForm inherits from FlaskForm which is a subclass that's csrf secure, and was the reason preventing validation.问题是子表单 IngredientsForm 从 FlaskForm 继承,这是一个 csrf 安全的子类,并且是阻止验证的原因。 You don't need this as you have already the token in the main form.您不需要这个,因为您已经在主表单中拥有令牌。

Instead, have it inherit from wtforms.Form which doesn't have that.相反,让它继承自没有那个的 wtforms.Form 。 Another way is to disable csrf during init, but the previous method is preferred.另一种方法是在 init 期间禁用 csrf,但首选前一种方法。

You can disable csrf protection for the FlaskForm by setting the flag to false within the class Meta .您可以通过在Meta类中将标志设置为 false 来禁用FlaskForm的 csrf 保护。 CSRF protection is not necessary for nested forms as long as the parent form takes over this task.只要父表单接管此任务,嵌套表单就不需要 CSRF 保护。

class IngredientsForm(FlaskForm):
    class Meta:
        csrf = False
    ingredient_name = StringField("Ingredient", validators=[DataRequired()])

class RecipeForm(FlaskForm):
    recipe_name = StringField("Recipe name", validators=[DataRequired()])
    ingredients = FieldList(FormField(IngredientsForm), min_entries=2, max_entries=5)
    submit = SubmitField("Submit")

An alternative is to inherit from Form .另一种方法是从Form继承。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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