Python 嵌套的WTForms字段列表在字段中生成HTML

Python 嵌套的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

我看到了同样奇怪的行为,我的原始字段是用HTML而不是默认值呈现的。在另一个例子中,基本上是一个字段列表在单个FormField上的单层深度堆叠。在我的例子中,我创建了一个二维结构,一个字段列表覆盖一个表单字段上的字段列表。我不知道我现在在哪里

app.py

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代码。