基于配置文件的动态 WTF 表单

Dynamic WTF Forms based on a config File

我正在尝试根据配置文件生成表单定义。该代码仅用于测试目的:

from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired
class B2BForm(FlaskForm):
  products = list()
  for i in range(0,4):
      products.append(StringField('Name asd '+str(i), validators=[DataRequired()]))

然后我渲染我的表单:

{% for p in form.products %}
  <div class="form-group">
      <label for="password">Label: {{p.label}}</label>
      {% for error in p.errors %}
          <div style="color: red;">[{{ error }}]</div>
      {% endfor %}
    </div>
 {% endfor %}

不幸的是,这不起作用:(循环有效,但无法呈现项目。有什么想法吗?

我认为这是您的 class 构造。我相信 wtf 表单需要严格的格式; class 属性是一个 wtf_Field 不是字段列表。试试看

def index():
    def B2BForm():
        class _B2BForm(FlaskForm):
            prod_list = list()
            pass
        for i in range(4):
            setattr(_B2BForm, 'product_' + str(i), StringField('Name asd ' + str(i), validators=[DataRequired()]))
            _B2BForm.prod_list.append(str(i))
        return _B2BForm()
    return render_template('index.html', form=B2BForm())

[请注意,您也可以使用 metaclasses 和 __metaclass__ 进行此类构造,并且可能在 def __init__(self) 中,但我没有尝试过这些并且更喜欢以上构造形式]

然后您需要更改您的 jinja2 以循环遍历您的属性 'product_0'、'product_1' 等,如下所示:

{% for p_int in form.prod_list %}
        <div class="form-group">
            <label for="password">Label: {{ form['product_'+p_int].label }}</label>
            {% for error in form['product_'+p_int].errors %}
                <div style="color: red;">[{{ error }}]</div>
            {% endfor %}
        </div>
{% endfor %}

您也可以将其用作动态构造函数,因此如果您的产品数量发生变化,请将 N 替换为 4,并将 N 作为函数的参数。 FlaskForms 不允许显式动态构建。