使用wtforms动态添加输入字段

mut*_*han 12 python jinja2 flask wtforms flask-wtforms

我不太确定如何解决这个问题.我希望我能到达那里.

例如,我在一个页面上有一个充满地址的表.这些是动态的(可以是5或10或任何其他计数).我希望有可能在一个页面上编辑它们.

我的方法是创建wtforms表单编辑一个地址,并乘以它在Jinja2的for loop和附加到HTML propertys nameidloop.index0从itereation,这样我就可以提取人工数据的每一行,并把它放回我的形式,当我想评估它.

因此,此示例的表单将是:

class AdressForm(Form):
    name = TextField()
Run Code Online (Sandbox Code Playgroud)

所以现在我的模板aproach看起来如下(分解为一个输入字段):

{% for address in addresses %}
    {{ forms.render_field(addressform.name, id = "name_" ~ loop.index0, 
                          name = "name_" ~ loop.index0, value = address.name) }}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

(forms.render_field只是一个宏,用于指定wtforms的字段函数的正确类.就像它们在许多教程中使用的那样)

所以这不起作用,因为你不能name手动将参数传递给字段函数,因为wtforms name从初始Form的variblename创建html-paramter.

那么有没有办法将前缀或后缀添加到我想要呈现的表单的名称.或者这是一个XY问题,我的方法总是错误的.

或者我自己一点都做(我真的试图避免这种情况)

Sea*_*ira 24

WTForms有一个叫做的元字段FormField和另一个叫做的元字段FieldList.这两个组合在一起可以得到你想要的东西:

class AddressEntryForm(FlaskForm):
    name = StringField()

class AddressesForm(FlaskForm):
    """A form for one or more addresses"""
    addresses = FieldList(FormField(AddressEntryForm), min_entries=1)
Run Code Online (Sandbox Code Playgroud)

要在AddressesForm中创建条目,只需使用字典列表:

user_addresses = [{"name": "First Address"},
                  {"name": "Second Address"}]
form = AddressesForm(addresses=user_addresses)
return render_template("edit.html", form=form)
Run Code Online (Sandbox Code Playgroud)

然后,在您的模板中,只需循环遍历子表单:

{% from 'your_form_template.jinja' import forms %}
{% for address_entry_form in form.addresses %}
    {{ address_entry_form.hidden_tag() }}
    {# Flask-WTF needs `hidden_tag()` so CSRF works for each form #}
    {{ forms.render_field(address_entry_form.name) }}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

WTForms将自动为名称和ID添加正确的前缀,因此当您发回数据时,您将能够获取form.addresses.data并获取包含更新数据的词典列表.

  • 请注意,“Form”已被弃用(使用“FlaskForm”)。我还认为“render_field”方法不再有效。只需调用“address_entry_form.name”即可 (3认同)
  • @alexfvolk您的问题是否在某处回答? (2认同)
  • 要使用 CSRF 令牌,请确保将 `hidden_​​tag()` 添加到两个表单中。所以在这个例子中,需要`{{ form.hidden_​​tag() }}`和`{{ address_entry_form.hidden_​​tag() }}`。 (2认同)

Ty *_*man 6

Sean Vieira 的回答StringFields(以前TextField)很有用,但对于 dynamic 来说事情变得有点棘手SelectFields。对于如何实现动态有趣的人SelectFieldswtforms,看/sf/answers/4028395661/