"Not a valid choice" 仅在添加 Bootstrap 后才在 SelectField 中

"Not a valid choice" in SelectField Only After Adding Bootstrap

我正在尝试在 Flask 中构建一个非常基本的应用程序:一个接受用户一些输入的单一表单(我是网络开发的新手)。我最初能够启动它并 运行,但是当我尝试修改 HTML 以包含 Bootstrap 时,我在单击提交按钮时收到 Not a valid choice 错误。

主应用程序:

from flask import Flask, render_template, flash, session, redirect, url_for, request
from forms import CustomAnalyticsMenu

app = Flask(__name__)

app.config['SECRET_KEY'] = 'mysecretkey'

@app.route('/')
@app.route('/home')
def home():
    return render_template('home.html')

@app.route('/custom_analytics_menu', methods=['GET', 'POST'])
def custom_analytics_menu():
    form = CustomAnalyticsMenu()

    if form.validate_on_submit():
        print("validated_on_submit")
        session['menu_item'] = form.menu_item.data
        return redirect(url_for('submission'))

    else:
        print(form.errors)

    return render_template('custom_analytics_menu.html', form=form)

@app.route('/submission', methods=['GET', 'POST'])
def submission():
    return render_template('submission.html')

if __name__ == '__main__':
    app.run(debug=True)

形式:

from flask_wtf import FlaskForm
from wtforms import StringField, RadioField, SelectField, SubmitField
from wtforms.validators import DataRequired

class CustomAnalyticsMenu(FlaskForm):
    menu_item = SelectField('Menu Item:', choices=[('option_one', 'Option One'),
                                                    ('option_two', 'Option Two'),
                                                    ('option_three', 'Option Three')])
    generate_deck = SubmitField('Generate deck')

HTML:

这是有效的 HTML 代码:

{% extends "layout.html" %}

{% block content %}

<div>
  <form method="POST" action="">
      {{ form.hidden_tag() }}

      {{ form.menu_item.label }} {{ form.menu_item }}

      {{ form.generate_deck() }}
  </form>
</div>

{% endblock %}

但是,当我更改这部分时:

{{ form.menu_item.label }} {{ form.menu_item }}

为此:(我从这里得到的:https://getbootstrap.com/docs/4.0/components/forms/#form-controls

<div class="form-group">
    <label for="menu_item">{{ form.menu_item.label }}</label>
    <select class="form-control" id="menu_item">
    {% for item in form.menu_item.choices %}
        <option>{{ item[-1] }}</option>
    {% endfor %}
    </select>
</div>

我的 SelectField 在功能上看起来是一样的(除了显然它有 Bootstrap 样式),但是现在当我点击提交按钮时,没有任何反应,我得到错误 Not a valid choice .这是我正在尝试做的事情的一个片段,我也有一个 RadioField 和一个 StringField 但是我在尝试应用类似的样式时也遇到了同样的错误。有人可以帮助我了解我哪里出错了吗?

编辑以在 <select> 字段上包含 name 属性作为附加问题的解决方案,并在 @RaghavPaliwal 的回答中进一步解释。

您传递给 SelectFieldchoicesa sequence of (value, label) pairs。 在您的示例中,这些是:

[('option_one', 'Option One'), 
 ('option_two', 'Option Two'), 
 ('option_three', 'Option Three')]

这些元组的第一个元素是选项代表的实际值,并且对您的应用程序有意义。它需要设置为 <option> 标签的 value 属性。每个元组中的第二个元素只是一个格式良好的表示形式,表示选项代表显示给用户的值。

因此,您需要为每个 <option> 标签提供一个 value 属性:

<div class="form-group">
    <label for="menu_item">{{ form.menu_item.label }}</label>
    <select class="form-control" id="menu_item" name="menu_item">
    {% for val, text in form.menu_item.choices %}
        <option value="{{ val }}">{{ text }}</option>
    {% endfor %}
    </select>
</div>

如果您不为 <option> 标签提供 value 属性,标签的内容将作为表单字段的值传递。在您的情况下,这意味着如果选择了 'Option One',则字符串 'Option One' 将作为字段的值传递。然后表单验证测试它是否包含在选项值之一 'option_one''option_two''option_three' 中,因此验证失败。

我想我明白了!我看到了另一个 StackedOverflow 问题 (),他们的 <select> 中有一个 name 字段。我更新了我的 (value, label) 对,使它们匹配(即 ('Option One', 'Option One') 而不是 ('option_one', 'Option One'))并将代码更新为:

<div class="form-group">
      <label for="menu_item">{{ form.menu_item.label }}</label>
      <select class="form-control" name="menu_item">
        {% for item in form.menu_item.choices %}
          <option>{{ item[-1] }}</option>
        {% endfor %}
      </select>
  </div>

成功了!或者,我可以让 (value, label) 对保持不变,并使用上面 SuperShoot 的答案中的代码。我不能说我完全理解 为什么 需要 name 标签,所以如果有人对此有解释,我很想听听。