Flask WTForms BooleanField UnboundField

时间:2018-11-16 15:26:52

标签: python flask wtforms

我正在编写一个脚本,该脚本通常从数据库中检索5行,并且希望将其显示为复选框列表。

但是它无法正确显示:显示为“ UnboundField”

form.py

class ExampleForm(FlaskForm):
    [...query & results...]
    for line in results_sql:
        list_checkbox[line.label] = BooleanField(line.label)

routes.py

@bp.route('/example')
def example():
    form = ExampleForm()
    return render_template("index.html", form=form)

index.html

<table class="table table-bordered table-condensed">
    {% for checkbox in form.list_checkbox %}
    <tr>
        <td>{{ checkbox }}</td>
        <td>{{ form.list_checkbox[checkbox ] }}</td>
    </tr>
    {% endfor %}
</table>

结果:

rendered table

1 个答案:

答案 0 :(得分:0)

您已将字段放入嵌套字典中。表单无法处理任意容器,因此无法绑定此类字段。

相反,您需要将字段放在field enclosure中。我将使用FormField() field指向嵌套的Form类。您可以通过调用BaseForm() constructor来生成嵌套的Form类:

  

BaseForm 提供的是用于存储字段的容器,它将在实例化时绑定,并保存在内部字典中。通过对BaseForm实例的Dict样式访问,您可以访问(和修改)封闭的字段。

然后,当您创建ExampleForm()类的实例时,它将绑定FormField字段,然后该字段又创建一个嵌套表单对象的实例,该实例然后绑定每个您输入的BaseForm()

字段

由于调用BaseForm(fields)将创建一个表单 instance ,因此您确实需要先将其包装在函数中,然后才能将其用作嵌套表单:

def form_from_fields(fields):
    def create_form(prefix='', **kwargs):
        form = BaseForm(fields, prefix=prefix, meta=FlaskForm.Meta)
        form.process(**kwargs)
        return form
    return create_form

class ExampleForm(FlaskForm):
    # ...

    list_checkbox = FormField(
        form_from_fields(
            [(line.label, BooleanField(line.label)) for line in results_sql]
        )
    )

BaseForm()不会像Form类那样处理任何数据,因此您需要将FormField()传递给创建实例的参数传递给.process()方法在返回实例之前。

渲染时在list_checkbox字段上进行迭代时,可以直接获取字段,并从字段对象获取标签:

<table class="table table-bordered table-condensed">
    {% for checkbox in form.list_checkbox %}
    <tr>
        <td>{{ checkbox.label }}</td>
        <td>{{ checkbox }}</td>
    </tr>
    {% endfor %}
</table>

演示(使用基本的WTForms库,但是Flask-WTF过程相同)

>>> from wtforms.form import BaseForm, Form
>>> from wtforms.fields import BooleanField, FormField
>>> fields = ['Calendrier', 'Commentaire', 'Dessin', 'Ex-libris', 'Gravure']
>>> def form_from_fields(fields):
...     def create_form(prefix='', **kwargs):
...         form = BaseForm(fields, prefix=prefix)
...         form.process(**kwargs)
...         return form
...     return create_form
...
>>> class ExampleForm(Form):
...     list_checkbox = FormField(form_from_fields([(field, BooleanField(field)) for field in fields]))
...
>>> form = ExampleForm()
>>> form.list_checkbox
<wtforms.fields.core.FormField object at 0x1232a76d8>
>>> list(form.list_checkbox)
[<wtforms.fields.core.BooleanField object at 0x1232a77f0>, <wtforms.fields.core.BooleanField object at 0x1232a78d0>, <wtforms.fields.core.BooleanField object at 0x1232a7978>, <wtforms.fields.core.BooleanField object at 0x1232a7a20>, <wtforms.fields.core.BooleanField object at 0x1232a7ac8>]
>>> print(*form.list_checkbox, sep='\n')
<input id="list_checkbox-Calendrier" name="list_checkbox-Calendrier" type="checkbox" value="y">
<input id="list_checkbox-Commentaire" name="list_checkbox-Commentaire" type="checkbox" value="y">
<input id="list_checkbox-Dessin" name="list_checkbox-Dessin" type="checkbox" value="y">
<input id="list_checkbox-Ex-libris" name="list_checkbox-Ex-libris" type="checkbox" value="y">
<input id="list_checkbox-Gravure" name="list_checkbox-Gravure" type="checkbox" value="y">

然后,FormField()字段还可以确保您可以为表单设置默认值,或者可以确保再次发布表单时可以访问数据集:

>>> form = ExampleForm(list_checkbox={'Calendrier': True})
>>> print(form.list_checkbox['Calendrier'])
<input checked id="list_checkbox-Calendrier" name="list_checkbox-Calendrier" type="checkbox" value="y">
>>> print(form.list_checkbox['Commentaire'])
<input id="list_checkbox-Commentaire" name="list_checkbox-Commentaire" type="checkbox" value="y">