Flask/Python/WTForms验证并动态设置SelectField选择 [英] Flask / Python / WTForms validation and dynamically set SelectField choices

查看:92
本文介绍了Flask/Python/WTForms验证并动态设置SelectField选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个简单的 Flask / Python 单页Web应用程序,该应用程序为SelectField使用动态创建的选择.

I'm trying to create a simple Flask / Python one page web app that uses dynamically created choices for a SelectField.

但是,我无法使用动态创建的选项将其发布到POST,并且还有一些有趣的验证行为(将在代码后进行解释)

However, I can't get it to POST using dynamically created choices, and there's also some funny validation behaviour going on (will explain after the code)

我在这里创建了一个最小的失败示例:

I created a minimum failing example here:

from flask import Flask, render_template, flash, redirect
from flask_wtf import Form
from wtforms import IntegerField, SubmitField, SelectField
from wtforms.validators import DataRequired, NumberRange, Optional

# Set up app and config    
DEBUG = True
SECRET_KEY = '42721564'
app = Flask(__name__)
app.config.from_object(__name__)

# Main stuff starts here

class SelectFieldForm(Form):
    default_field = SelectField('Default Set SelectField', choices=[(i, i) for i in range(0,60,5)], coerce=int)
    default_field_2 = SelectField('Default Set SelectField', choices=[(i, i) for i in range(0,60,5)], coerce=int)
    dynamic_field = SelectField('Dynamically Set Selectfield', choices=[], validators=[Optional()], coerce=int)

    get_default_field_value_difference = SubmitField(label='Get Default Field Difference')
    deduct_dynamic_field_value = SubmitField(label='Deduct Dynamic Field Value')


@app.route('/mfe-dynamic-selectfield', methods=['GET', 'POST'])
def failingSelectField():
    form = SelectFieldForm()

    if form.validate_on_submit():
        print("validated")

        difference = form.default_field_2.data - form.default_field.data

        if form.get_default_field_value_difference.data:
            flash( difference )
            form.dynamic_field.choices = [(i,i) for i in range(0,difference,5)]

            return render_template('mfe-dynamic-selectfield.html', form=form)

        if form.deduct_dynamic_field_value.data:

            if form.dynamic_field.data:
                deducted = difference - form.dynamic_field.data
                flash( deducted )

            else:
                flash( "no dynamic field value chosen")           

            return render_template('mfe-dynamic-selectfield.html', form=form)

        else:
            flash( "nope" )

    return render_template('mfe-dynamic-selectfield.html', form=form)

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

打开页面可以正常工作,并且按预期立即闪烁不".

Bringing up the page works just fine, and immediately flashes "nope", as expected.

计算默认设置字段之间的差异:-只要它们都设置为"0"就可以工作-如果任何一个字段都未设置为"0",则其他所有POST都无法通过验证,并且该时间正确计算了差值并动态设置了最后一个字段.

Calculating the difference between the default set fields: -works every time as long they are both set to '0' -if either field is not set to '0', every other POST fails validation, and the time correctly calculates the difference and dynamically sets the last field.

每次使用动态设置字段尝试POST都会失败.

Trying to POST using the dynamically set field fails every time.

我在这里错过了很明显的东西吗?

Am I missing something very obvious here?

我正在使用此渲染:

{% block content %}
<form action="" method="post" name="mfe-dynamic-selectfield">
  {{ form.hidden_tag() }}
  <table>
  <tr>
      <td> Calculated value </td>
      <td>

      {% with messages = get_flashed_messages() %}
          {% if messages %}
            <ul class=flashes>
            {% for message in messages %}
              <li>{{ message }}</li>
            {% endfor %}
            </ul>
          {% endif %}
       {% endwith %}

       </td>
  </tr>

  <br>
  <tr>
      <td>Default SelectField 1</td>
      <td>Default SelectField 2</td>

      <td>Dynamic Selectfield</td>
  </tr>

  <br>

  <tr>
      <td>{{ form.default_field }}</td>
      <td>{{ form.default_field_2 }}</td>

      <td>{{ form.dynamic_field }}</td>
  </tr>

  <tr>
      <td>{{ form.get_default_field_value_difference }}</td>
      <td>{{ form.deduct_dynamic_field_value }}</td>
  </tr>      

  </table>
</form>
{% endblock %}

推荐答案

每隔一次失败,因为 form.dynamic_field 的值在 0 无.仅当值为 None (无)时,表单才通过验证.

It's failing every other time because the value of form.dynamic_field is oscillating between 0 and None. The form passes validation only when the value is None.

这是因为在验证时, form.dynamic_field.choices [] (一个空列表).因此,那里出现的任何价值都会被拒绝.您可能想在尝试验证之前 动态设置选项;也许是这样的:

This is because form.dynamic_field.choices is [] (an empty list) at the time of validation. So any value that comes there is rejected. You probably want to dynamically set the choices before you try the validating; maybe with something like this:

@app.route('/mfe-dynamic-selectfield', methods=['GET', 'POST'])
def failingSelectField():
    form = SelectFieldForm()

    # Calculate dynamic field choices
    try:
        difference = form.default_field_2.data - form.default_field.data
        form.dynamic_field.choices = [(i,i) for i in range(0,difference,5)]
    except TypeError:
        pass

    if form.validate_on_submit():
        # (continue as usual)

现在,表单将按预期验证.

Now the form will validate as expected.

当然,您可能应该在前面添加一些代码,以确保 default_field 确实具有有效的选择值(不仅仅是两个整数).另一种选择是将 dynamic_field 设置为第二种形式.然后,您可以验证第一个表单,并使用其值来计算第二个表单的有效选择.

Of course, you should probably add some code in front to make sure that the default_fields do have valid choices values (not just any two integers). Another option is to put dynamic_field in a second form. Then you can validate the first form, and use its values to calculate valid choices for the second one.

这篇关于Flask/Python/WTForms验证并动态设置SelectField选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆