嵌套的WTForms FieldList在字段中产生HTML

时间:2019-05-06 22:03:10

标签: python flask flask-wtforms wtforms fieldlist

我看到相同的奇怪行为发布到Filling WTForms FormField FieldList with data results in HTML in fields,其中我的原始字段是使用HTML而不是默认值呈现的。在另一个示例中,基本上是在单个FormField上对FieldList进行了一层深层堆叠。在我的情况下,我正在FormField上的FieldList上创建FieldList的2D结构。我不知道我在哪里。

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

templates / 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>

Nested Field List rendering HTML

1 个答案:

答案 0 :(得分:1)

以通常的方式在视图中设置所有字段值,但在模板中,将.data属性用于属于嵌套表单的字段:

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

关于它的价值,在处理嵌套的FieldList时还有另一个陷阱:如果以逻辑方式构造表单,由于idname属性的名称将不完全命名空间.append_entry()的工作方式。结果,期望值将不会发布,并且验证也将中断。

损坏:

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)