Вложенный WTForms FieldList приводит к HTML в полях - PullRequest
1 голос
/ 07 мая 2019

Я вижу такое же странное поведение, опубликованное в Заполнение WTForms FormField FieldList данными приводит к HTML в полях , где мои необработанные поля отображаются с HTML, а не с их значениями по умолчанию. В этом другом примере, по сути, имеется один уровень глубокого стека FieldList над одним FormField. В моем случае я создаю 2D-структуру FieldList поверх FieldList поверх 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>

Nested Field List rendering HTML

1 Ответ

1 голос
/ 04 июня 2019

Установите все значения полей обычным способом в вашем представлении, но в вашем шаблоне используйте поле .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 %}

Для чего бы то ни было, при работе с вложенными полевыми списками есть еще одна проблема: если вы создаете форму логическим способом, атрибуты полей id и name не будут полностью разделены именами из-за способа .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)
...