【问题标题】:"Not a valid choice" in SelectField Only After Adding Bootstrap仅在添加引导程序后 SelectField 中的“不是有效选择”
【发布时间】:2020-01-01 03:36:18
【问题描述】:

我正在尝试在 Flask 中构建一个非常基本的应用程序:一个接受来自用户的一些输入的单一表单(我是 Web 开发的新手)。最初我能够启动并运行它,但是当我尝试修改 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。这是我正在尝试做的一个 sn-p,我也有一个 RadioField 和一个 StringField 但在尝试应用类似样式时我也会遇到同样的错误。有人可以帮助我了解我哪里出错了吗?

【问题讨论】:

    标签: python bootstrap-4 flask-wtforms wtforms


    【解决方案1】:

    我想我明白了!我看到另一个 StackedOverflow 问题 (Why is my flask form validation returning Not a valid choice?),他们的 &lt;select&gt; 中有一个 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 标签,所以如果有人对此有解释,我很想听听。

    【讨论】:

    • 是的,name 属性是必需的,因为该字段的值在表示发送到服务器的表单的映射中被键入该名称。我应该把它和你的其他错误一起捡起来。选项标记的value 属性的作用是,它通常会被设置为代表数据库表中一行的主键的值。在这种情况下,值将为1,而标签为'Option One'。无论如何,很高兴你能成功!
    【解决方案2】:

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

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

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

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

    因此,您需要为每个&lt;option&gt; 标签提供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>
    

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

    【讨论】:

    • 感谢您的回复!不幸的是,这不起作用,我仍然得到相同的Not a valid choice 错误:(
    • 我也尝试使值和标签相同(这样即使它默认为标签也可以),但这也没有用
    • 我想我明白了!请参阅下面的评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    • 1970-01-01
    • 2014-05-26
    • 2017-08-26
    • 1970-01-01
    • 2021-12-16
    • 2016-09-10
    相关资源
    最近更新 更多