使用wtforms动态添加输入字段

时间:2015-02-06 22:02:03

标签: python flask jinja2 wtforms flask-wtforms

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

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

我的方法是创建一个带有wtforms的表单来编辑一个地址并相乘 它在jinja2 for loop中附加到html属性nameid 来自迭代的loop.index0,因此我可以手动提取每行数据 当我想评估它时,把它放回我的形式。

所以这个例子的表格是:

class AdressForm(Form):
    name = TextField()

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

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

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

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

那么有没有办法在我想渲染的表单名称中添加前缀或后缀。 或者这是一个XY问题,我的方法完全是错误的。

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

2 个答案:

答案 0 :(得分:19)

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

class AddressEntryForm(Form):
    name = TextField()

class AddressesForm(Form):
    """A form for one or more addresses"""
    addresses = FieldList(FormField(AddressEntryForm), min_entries=1)

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

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

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

{% 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 %}

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

答案 1 :(得分:1)

Sean Vieira's answer对于StringFields(以前是TextField)非常有用,但是对于动态SelectFields来说有些麻烦。如果您对如何通过SelectFields实现动态wtforms感兴趣,请参见https://stackoverflow.com/a/57548509/7781935