FieldList 中动态调整的表单
Dynamically adjusted forms inside FieldList
我正在使用 Flask 和 Flask-WTF,我需要创建一个包含多个具有相似结构的块(子表单)的表单(比如一个包含一个 SelectField
和一个 TextAreaField
的子表单) ).作为 docs suggest, I can use FormField
together with FieldList
to achieve this goal. However, I need to tweak my SelectField
's dynamically (changing their choice
s at runtime according to values in the database). The docs now suggest
Note that the choices keyword is only evaluated once, so if you want to make a dynamic drop-down list, you’ll want to assign the choices list to the field after instantiation.
可以找到这种方法的示例 。然而,FormField
正在接受 form_class
,而不是一个实例(至少,根据文档),所以这两个配方似乎不能很好地结合在一起。
还有其他想法吗?
好的,这比我想象的要容易。您必须创建那些带有空选项的子表单,创建它们的列表,然后调整列表项中的选项。
class UserForm(wtforms.Form):
# must inherit from wtforms.Form, not flask-WTForms'
# see
first_name = StringField('First Name', [validators.DataRequired()])
last_name = StringField('Last Name', [validators.DataRequired()])
accepted_policy = BooleanField('Accept Policy')
experience = SelectField('Experience', coerce=int)
class UsersForm(Form):
users = FieldList(FormField(UserForm), min_entries=2)
@app.route('/', methods=['GET', 'POST'])
def hello_world():
form = UsersForm(users=[{}, {}, {}])
form.users[0].experience.choices=[(1, 'One'), (2, 'Two')]
form.users[1].experience.choices = [(1, 'Uno'), (2, 'Du')]
form.users[2].experience.choices = [(0, 'Zero')]
return render_template("hello.html", form=form)
这是一个模板:
{% macro render_field(field) %}
<dt>{{ field.label }}
<dd>{{ field(**kwargs)|safe }}
{% if field.errors %}
<ul class=errors>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</dd>
{% endmacro %}
<form method=post>
<dl>
{{ form.hidden_tag()}}
{% for user_entry_form in form.users %}
{{ user_entry_form.name }}
{{ render_field(user_entry_form.first_name) }}
{{ render_field(user_entry_form.last_name) }}
{{ render_field(user_entry_form.experience) }}
{% endfor %}
</dl>
<p><input type=submit value=Go!>
</form>
我正在使用 Flask 和 Flask-WTF,我需要创建一个包含多个具有相似结构的块(子表单)的表单(比如一个包含一个 SelectField
和一个 TextAreaField
的子表单) ).作为 docs suggest, I can use FormField
together with FieldList
to achieve this goal. However, I need to tweak my SelectField
's dynamically (changing their choice
s at runtime according to values in the database). The docs now suggest
Note that the choices keyword is only evaluated once, so if you want to make a dynamic drop-down list, you’ll want to assign the choices list to the field after instantiation.
可以找到这种方法的示例 FormField
正在接受 form_class
,而不是一个实例(至少,根据文档),所以这两个配方似乎不能很好地结合在一起。
还有其他想法吗?
好的,这比我想象的要容易。您必须创建那些带有空选项的子表单,创建它们的列表,然后调整列表项中的选项。
class UserForm(wtforms.Form):
# must inherit from wtforms.Form, not flask-WTForms'
# see
first_name = StringField('First Name', [validators.DataRequired()])
last_name = StringField('Last Name', [validators.DataRequired()])
accepted_policy = BooleanField('Accept Policy')
experience = SelectField('Experience', coerce=int)
class UsersForm(Form):
users = FieldList(FormField(UserForm), min_entries=2)
@app.route('/', methods=['GET', 'POST'])
def hello_world():
form = UsersForm(users=[{}, {}, {}])
form.users[0].experience.choices=[(1, 'One'), (2, 'Two')]
form.users[1].experience.choices = [(1, 'Uno'), (2, 'Du')]
form.users[2].experience.choices = [(0, 'Zero')]
return render_template("hello.html", form=form)
这是一个模板:
{% macro render_field(field) %}
<dt>{{ field.label }}
<dd>{{ field(**kwargs)|safe }}
{% if field.errors %}
<ul class=errors>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
</dd>
{% endmacro %}
<form method=post>
<dl>
{{ form.hidden_tag()}}
{% for user_entry_form in form.users %}
{{ user_entry_form.name }}
{{ render_field(user_entry_form.first_name) }}
{{ render_field(user_entry_form.last_name) }}
{{ render_field(user_entry_form.experience) }}
{% endfor %}
</dl>
<p><input type=submit value=Go!>
</form>