【问题标题】:SelectField : why returning "Not a valid choice error"?SelectField:为什么返回“不是有效的选择错误”?
【发布时间】:2021-02-10 17:42:38
【问题描述】:

我是python的菜鸟,所以这可能是一个愚蠢的问题,抱歉。

contact.html

{% extends 'layout.html' %}

{% block content %}

    <form method="POST" action="/">
    
       <fieldset class="form-field">
        {{ form.iro.label }}<br>
        {{ form.iro }}
        {% if form.iro.errors %}
          <ul class="errors">
            {% for error in form.iro.errors %}
            <li>{{ error }}</li>
            {% endfor %}
          </ul>
        {% endif %}
      </fieldset><br>
      
      {{ form.sub_issue }}

      </form>
  </div>

{% endblock %}

forms.py

from flask_wtf import FlaskForm
from wtforms import StringField, TextField, SubmitField, FieldList, FormField, SelectField, Form
from wtforms.validators import DataRequired, Length, Optional


class ContactForm(FlaskForm):
    """Contact form."""
    iro = SelectField(
        'IRO',
        choices=[]
    )
    
    sub_issue = SubmitField('Open an issue')

在我的代码中,我使用来自请求的 json 填充 SelectField 的选择参数

@app.route('/', methods=('GET', 'POST'))
def contact():
    form = ContactForm()
    if request.method == 'GET':
      r = requests.get("https://...",verify=False)
      form.iro.choices= [(iro,iro) for iro in list(r.json().values())]
      return render_template('contact.html', form=form)
    else:
      if form.validate_on_submit():
      #code when submitted...

但是当我点击提交按钮时,我的 SelectField 下会出现“Not a valid choice”错误

你知道为什么吗?

【问题讨论】:

  • 总是将完整的错误消息(从单词“Traceback”开始)作为文本(不是截图,不是链接到外部门户)有问题(不是评论)。还有其他有用的信息。
  • 也许首先使用print() 来查看contact() 中变量的值,也许你会看到它是否在SelectField 中得到正确的值。如果它得到错误的值,那么也许它可以帮助你修复它。
  • GET 中,您将值添加到choices,但是当您运行else: 并检查validate_on_submit(): 时,您在choices 中没有这些值 - 所以它无法检查是否您选择了正确的值,它会发送"Not a valid choice"。在这两种情况下,您都必须将它们添加到choices - 在GETPOST 中。也许在从 http://...` 获取之后,将它们保存在全局变量中,然后在检查 else 之前再次将它们添加到 choices validate_on_submit():

标签: python json flask flask-wtforms


【解决方案1】:

我无法对其进行测试,但对我而言,所有问题都是您仅在 GET 中向 choices 添加值。当你为POST 运行validate_on_submit(): 时,choices 是空的,它总是会给出“不是有效的选择”

你会需要这样的东西。

@app.route('/', methods=('GET', 'POST'))
def contact():
    form = ContactForm()

    r = requests.get("https://...", verify=False)
    form.iro.choices = [(iro,iro) for iro in list(r.json().values())]

    if request.method == 'GET':
      return render_template('contact.html', form=form)
    else:
      if form.validate_on_submit():
      #code when submitted...

如果requests 总是得到相同的值,那么你应该在开始时只读取一次(在contact() 之外),写入本地文件或数据库并在contact() 中读取它们

如果requests 可能给出不同的值,那么您应该在GET 中读取它们,以uniqe 名称保存在文件中(或在具有uniqe ID 的数据库中)并将此名称/ID 作为隐藏字段发送到HTML。稍后在POST 中,您应该使用这个唯一的名称/ID 从文件/数据库中读取。

或多或少

@app.route('/', methods=('GET', 'POST'))
def contact():
    form = ContactForm()

    if request.method == 'GET':

      r = requests.get("https://...", verify=False)
      form.iro.choices = [(iro,iro) for iro in list(r.json().values())]

      save r.json() in unique file

      form.hidden_field = unique_file

      return render_template('contact.html', form=form)
    else:

      unique_file = form.hidden_field

      read r.json() from unique file

      form.iro.choices = [(iro,iro) for iro in list(r.json().values())]

      if form.validate_on_submit():
      #code when submitted...

【讨论】:

  • 哦,谢谢!我尝试了这个解决方案,它正在工作。很奇怪的逻辑,但你的解决方案很好,谢谢。
猜你喜欢
  • 2020-02-27
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
  • 2023-03-27
  • 2017-08-26
  • 1970-01-01
  • 1970-01-01
  • 2016-09-10
相关资源
最近更新 更多