Flask WTForms 并使用 for 循环生成字段
Flask WTForms and generating fields with for loop
我想为过去 10 年的每一年创建一个包含字段的表单。因此,对于 2020-2011 年,我希望每年都有一个 IntegerField,变量名称为 year_2020、year_2019、year_2018,...如果它们也有适当的标签,那也很好, 即 2020, 2019...
我可以通过单独为每年写一些东西来做到这一点,但我认为使用 for 循环生成它们会更好、更有效 (?)。这可能吗?
我看到了 about generating fields in the template using a for loop but I'm wondering how to generate fields in the python form class itself (not sure what to call it; please excuse my ignorance). I've seen 但我似乎无法让它工作。我也不喜欢该解决方案,因为它没有为字段提供描述性名称,例如 year_2020.
到目前为止,这是我的代码;对任何错误表示歉意。
python:
forms.py
class YearForm(FlaskForm):
year = IntegerField(validators=[NumberRange(min=0,max=100000,message='Please enter an integer above 0.'),
InputRequired(message='Please enter a value.')])
class RentForm(FlaskForm):
years = FieldList(FormField(YearForm), min_entries=10)
模板:
form.html
for year in rentForm.years:
<p>{{ year.label }}: {{ year(size=32) }}
{% for error in year.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
我似乎在错误地访问模板中的字段。什么是正确的方法?以及如何为字段提供更具描述性的标签和变量名称?
如有任何帮助,我们将不胜感激;谢谢!
编辑:如果用另一种语言可以更轻松地完成此操作,请告诉我。我刚开始学习 Flask/Python,我也没有结婚。
我正在做类似的事情。也许我的例子会有所帮助。我正在扩展表单,在你的情况下 RentForm.years 在我的 Python 中的 Flask 处理程序中,NOT 在我的模板中。这是我的表格...
class TemplateFormRow(FlaskForm):
col = StringField(label='Column Name')
data_type = SelectField(label='Data Type',
choices=[("boolean", "boolean"), ("datetime", "datetime"),
("integer", "integer"), ("decimal", "decimal"), ("string", "string")])
sequence = HiddenField()
delete = SubmitField(label='Delete')
class TemplateForm(FlaskForm):
rows = FieldList(unbound_field=FormField(TemplateFormRow))
add_row = SubmitField(label='Add Row', render_kw={'class': "btn btn-primary"})
confirm = SubmitField(label='Save', render_kw={'class': "btn btn-primary"})
btn_cancel = SubmitField(label='Cancel', render_kw={'formnovalidate': True, 'class': "btn btn-primary"})
请注意,在我的示例中,我在父表单上放置了一个按钮,允许用户添加另一行。如果您总是想要 10 行,您的处理方式会有所不同。
这是使用此表单的 Python 代码的一部分。 append_entry 行对你特别重要...
if request.method == 'POST':
if form.btn_cancel.data:
return redirect(url_for('admin'))
if form.add_row.data: # User pressed the add row button
form.rows.append_entry()
这是呈现模板的 Python 代码...
return render_template(template_name_or_list='generic_entry_page.html', page_hdr='Template',
show_form=form, form_msg=msg)
最后,这是我的模板处理这个的部分...
{% for element in show_form %}
{% if element is iterable %} {# This is a vertical set of forms #}
<table>
<tr>
{% for field in element[0] %}
{# {% for field in element.rows[0] %}#}
{% if field.type != 'HiddenField' and field.label.text != 'CSRF Token' %}
<th>{{ field.label }}</th>
{% else %}
<th>{{ field }}</th>
{% endif %}
{% endfor %}
</tr>
{% for row in element %}
<tr>
{% for field in row %}
<td>
{% if field.type == 'SubmitField' %}
<button {{ field }} {{ field.label.text }} </button>
{% else %}
{{ field }}
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<br>
生成的屏幕如下所示...
这有帮助吗?
好的,我能够使用来自 的信息做出令人满意的玩具示例。
python:
class ImageForm(FlaskForm):
frequency = SelectField(choices=[('monthly', 'Monthly'),('weekly', 'Weekly')])
caption = StringField('Caption')
credit = StringField('Credit')
class TestForm(FlaskForm):
images = FieldList(FormField(ImageForm), min_entries=10)
模板:
<form action="" method="post">
{{ testForm.hidden_tag() }}
<table>
{% for image in testForm.images %}
<tr>
<td> {{ image['frequency'] }} </td>
<td> {{ image['caption'] }} </td>
<td> {{ image['credit'] }} </td>
</tr>
{% endfor %}
<table>
</form>
结果:
Rendered HTML (ignore all the tabs; I have a problem)
我觉得这个应该很适合我的需求。
PS:您可以像这样访问各个字段:
testForm.images[0]['frequency']
对于第一个下拉菜单。
我想为过去 10 年的每一年创建一个包含字段的表单。因此,对于 2020-2011 年,我希望每年都有一个 IntegerField,变量名称为 year_2020、year_2019、year_2018,...如果它们也有适当的标签,那也很好, 即 2020, 2019...
我可以通过单独为每年写一些东西来做到这一点,但我认为使用 for 循环生成它们会更好、更有效 (?)。这可能吗?
我看到了
到目前为止,这是我的代码;对任何错误表示歉意。
python:
forms.py
class YearForm(FlaskForm):
year = IntegerField(validators=[NumberRange(min=0,max=100000,message='Please enter an integer above 0.'),
InputRequired(message='Please enter a value.')])
class RentForm(FlaskForm):
years = FieldList(FormField(YearForm), min_entries=10)
模板:
form.html
for year in rentForm.years:
<p>{{ year.label }}: {{ year(size=32) }}
{% for error in year.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
我似乎在错误地访问模板中的字段。什么是正确的方法?以及如何为字段提供更具描述性的标签和变量名称?
如有任何帮助,我们将不胜感激;谢谢!
编辑:如果用另一种语言可以更轻松地完成此操作,请告诉我。我刚开始学习 Flask/Python,我也没有结婚。
我正在做类似的事情。也许我的例子会有所帮助。我正在扩展表单,在你的情况下 RentForm.years 在我的 Python 中的 Flask 处理程序中,NOT 在我的模板中。这是我的表格...
class TemplateFormRow(FlaskForm):
col = StringField(label='Column Name')
data_type = SelectField(label='Data Type',
choices=[("boolean", "boolean"), ("datetime", "datetime"),
("integer", "integer"), ("decimal", "decimal"), ("string", "string")])
sequence = HiddenField()
delete = SubmitField(label='Delete')
class TemplateForm(FlaskForm):
rows = FieldList(unbound_field=FormField(TemplateFormRow))
add_row = SubmitField(label='Add Row', render_kw={'class': "btn btn-primary"})
confirm = SubmitField(label='Save', render_kw={'class': "btn btn-primary"})
btn_cancel = SubmitField(label='Cancel', render_kw={'formnovalidate': True, 'class': "btn btn-primary"})
请注意,在我的示例中,我在父表单上放置了一个按钮,允许用户添加另一行。如果您总是想要 10 行,您的处理方式会有所不同。
这是使用此表单的 Python 代码的一部分。 append_entry 行对你特别重要...
if request.method == 'POST':
if form.btn_cancel.data:
return redirect(url_for('admin'))
if form.add_row.data: # User pressed the add row button
form.rows.append_entry()
这是呈现模板的 Python 代码...
return render_template(template_name_or_list='generic_entry_page.html', page_hdr='Template',
show_form=form, form_msg=msg)
最后,这是我的模板处理这个的部分...
{% for element in show_form %}
{% if element is iterable %} {# This is a vertical set of forms #}
<table>
<tr>
{% for field in element[0] %}
{# {% for field in element.rows[0] %}#}
{% if field.type != 'HiddenField' and field.label.text != 'CSRF Token' %}
<th>{{ field.label }}</th>
{% else %}
<th>{{ field }}</th>
{% endif %}
{% endfor %}
</tr>
{% for row in element %}
<tr>
{% for field in row %}
<td>
{% if field.type == 'SubmitField' %}
<button {{ field }} {{ field.label.text }} </button>
{% else %}
{{ field }}
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<br>
生成的屏幕如下所示...
这有帮助吗?
好的,我能够使用来自
python:
class ImageForm(FlaskForm):
frequency = SelectField(choices=[('monthly', 'Monthly'),('weekly', 'Weekly')])
caption = StringField('Caption')
credit = StringField('Credit')
class TestForm(FlaskForm):
images = FieldList(FormField(ImageForm), min_entries=10)
模板:
<form action="" method="post">
{{ testForm.hidden_tag() }}
<table>
{% for image in testForm.images %}
<tr>
<td> {{ image['frequency'] }} </td>
<td> {{ image['caption'] }} </td>
<td> {{ image['credit'] }} </td>
</tr>
{% endfor %}
<table>
</form>
结果: Rendered HTML (ignore all the tabs; I have a problem)
我觉得这个应该很适合我的需求。
PS:您可以像这样访问各个字段:
testForm.images[0]['frequency']
对于第一个下拉菜单。