Python 嵌套的WTForms字段列表在字段中生成HTML
我看到了同样奇怪的行为,我的原始字段是用HTML而不是默认值呈现的。在另一个例子中,基本上是一个字段列表在单个FormField上的单层深度堆叠。在我的例子中,我创建了一个二维结构,一个字段列表覆盖一个表单字段上的字段列表。我不知道我现在在哪里 app.pyPython 嵌套的WTForms字段列表在字段中生成HTML,python,flask,flask-wtforms,wtforms,fieldlist,Python,Flask,Flask Wtforms,Wtforms,Fieldlist,我看到了同样奇怪的行为,我的原始字段是用HTML而不是默认值呈现的。在另一个例子中,基本上是一个字段列表在单个FormField上的单层深度堆叠。在我的例子中,我创建了一个二维结构,一个字段列表覆盖一个表单字段上的字段列表。我不知道我现在在哪里 app.py import os from flask import Flask, redirect, render_template, request, send_file, url_for from flask_wtf import FlaskFor
import os
from flask import Flask, redirect, render_template, request, send_file, url_for
from flask_wtf import FlaskForm
from flask_wtf.csrf import CSRFProtect
from wtforms import FieldList, FormField, RadioField, TextAreaField, validators
app = Flask(__name__)
csrf = CSRFProtect(app)
SECRET_KEY = os.urandom(32)
app.config['SECRET_KEY'] = SECRET_KEY
#region FORMS
class TestCaseItem(FlaskForm) :
pass_fail_radio = RadioField( '' , choices=[('Pass','Pass'), ('Fail','Fail')] , default='Pass' , validators=[validators.DataRequired()] )
failure_message = TextAreaField(default='')
class TestCaseForm(FlaskForm) :
test_items = FieldList( FormField( TestCaseItem ))
class ManualTestForm(FlaskForm):
test_cases = FieldList( FormField(TestCaseForm))
#endregion
@app.route("/" , methods = ['POST', 'GET'])
def index():
form = ManualTestForm()
test_cases = ["test case {}".format(i) for i in range(5)]
devices = ["device {}".format(i) for i in range(3)]
# Expand the field list for each test case
for tc in test_cases :
tcf = TestCaseForm()
# expand its field list for each test device
for device in devices :
tci = TestCaseItem()
tci.failure_message = 'abc'
tcf.test_items.append_entry( tci )
form.test_cases.append_entry( tcf )
return render_template('test_template.html', form=form, test_cases=test_cases, devices=devices )
if __name__ == "__main__" :
app.run(debug=True, port=5001) # http://127.0.0.1:5001
模板/test_template.html
<html>
<head>
</head>
<body>
<h1>Manual Test Submission</h1>
<h2>Test Suite</h2>
<form method="post">
{{ form.csrf_token }}
<!--TEST CASES-->
<table>
<tr>
<th>Test Case ID</th>
{% for test_item in form.test_cases[0].test_items %}
{% set device = devices[loop.index0] %}
<th>TC Status: {{device}}</th>
<th>TC Input: {{device}}</th>{% endfor %}
</tr>
{% for test_case in form.test_cases %}
{{test_case.hidden_tag()}}
<tr>
<td>{{ test_cases[ loop.index0 ]}}</td>
{% for test_item in test_case.test_items %}
<td>{{ test_item.pass_fail_radio }}</td>
<td>{{ test_item.failure_message }}</td>{% endfor %}
</tr>{% endfor %}
</table>
</form>
</body>
</html>
手动提交测试
测试套件
{{form.csrf_token}
测试用例ID
{%用于表单中的测试项。测试项案例[0]。测试项%}
{%set device=devices[loop.index0]}
TC状态:{{device}
TC输入:{{device}{%endfor%}
{form.test_cases%}
{{test_case.hidden_tag()}
{{test_cases[loop.index0]}
{test_case.test_items%}
{{test\u item.pass\u fail\u radio}
{{test_item.failure_message}{%endfor%}
{%endfor%}
以视图中的常规方式设置所有字段值,但在模板中使用字段
。属于嵌套表单的字段的数据属性:
{% for test_case in form.test_cases %}
{{ test_case.hidden_tag() }}
{{ test_cases[loop.index0] }}
{% for test_item in test_case.test_items %}
{{ test_item.pass_fail_radio.data }}
{{ test_item.failure_message.data }}
{% endfor %}
{% endfor %}
值得一提的是,在处理嵌套字段列表时还有另一个难题:如果以逻辑方式构造表单,则由于.append\u entry()
的工作方式,字段id
和name
属性将无法完全命名。因此,预期值不会被发布,验证也会中断
破碎:
form = RecipientsForm()
for proprietor in proprietors:
proprietor_form = ProprietorForm()
# Set proprietor name in hidden input field.
proprietor_form.prop_name = proprietor['name']
# populate and append addresses to proprietor form.
for address in proprietor['addresses']:
address_form = AddressForm()
address_form.address = address['address']
address_form.address_type = address['type']
proprietor_form.addresses.append_entry(address_form)
form.proprietors.append_entry(proprietor_form)
form = RecipientsForm()
proprietors = proprietor_api_call()
# Populate and append proprietors to Recipients form.
for idx, proprietor in enumerate(proprietors):
proprietor_form = ProprietorForm()
proprietor_form.prop_name = proprietor['name']
form.proprietors.append_entry(proprietor_form)
# Populate and append addresses to Proprietor form.
for address in proprietor['addresses']:
address_form = AddressForm()
address_form.address = address['address']
address_form.address_type = address['type']
form.proprietors[idx].addresses.append_entry(address_form)
有效:
form = RecipientsForm()
for proprietor in proprietors:
proprietor_form = ProprietorForm()
# Set proprietor name in hidden input field.
proprietor_form.prop_name = proprietor['name']
# populate and append addresses to proprietor form.
for address in proprietor['addresses']:
address_form = AddressForm()
address_form.address = address['address']
address_form.address_type = address['type']
proprietor_form.addresses.append_entry(address_form)
form.proprietors.append_entry(proprietor_form)
form = RecipientsForm()
proprietors = proprietor_api_call()
# Populate and append proprietors to Recipients form.
for idx, proprietor in enumerate(proprietors):
proprietor_form = ProprietorForm()
proprietor_form.prop_name = proprietor['name']
form.proprietors.append_entry(proprietor_form)
# Populate and append addresses to Proprietor form.
for address in proprietor['addresses']:
address_form = AddressForm()
address_form.address = address['address']
address_form.address_type = address['type']
form.proprietors[idx].addresses.append_entry(address_form)
今天4king建议的GitHub问题修复对我来说很有效。你试过在模板中使用{{field.data}}
而不是只使用{{field}
吗?好的catch@Hugo,在模板中用{test\u item.failure\u message}
替换{test item.failure\u message.data}
确实奏效了。这是我没有尝试过的一种变体,所有的讨论都集中在python源代码中执行或不执行xxx.data=yyy
操作上。链接到相应的GitHub继续,发布一个答案,我会接受的。你知道还有一点仍然很神秘,那就是我没有修改pass\u fail\u radio元素的模板表达式。不知何故,这呈现得很好,但对于文本元素的内容来说却不是这样。可能它确实仍然损坏,但与文本字段不同,它无法传达该状态。检查元素中的复选框,它很可能在值属性或其他内容中包含HTML代码。