简体   繁体   English

Flask WTForms BooleanField UnboundField

[英]Flask WTForms BooleanField UnboundField

I am writing a script that normally retrieves 5 lines from the database and I want to display it as a checkbox list.我正在编写一个通常从数据库中检索 5 行的脚本,我想将其显示为复选框列表。

But it doesn't display correctly: it says " UnboundField "但它没有正确显示:它说“ UnboundField ”

form.py表单.py

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

routes.py路线.py

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

index.html索引.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>

Result:结果:

渲染表

You've put your fields inside a nested dictionary.您已将字段放入嵌套字典中。 The form can't bind such fields as it can't handle arbitrary containers.表单不能绑定这样的字段,因为它不能处理任意容器。

Instead, you need to put the fields in a field enclosure .相反,您需要将字段放在字段外壳中 I'd use a FormField() field to point to a nested Form class.我会使用一个FormField()字段来指向一个嵌套的Form类。 You can generate the nested Form class by calling the BaseForm() constructor :您可以通过调用BaseForm()构造函数来生成嵌套的Form类:

What BaseForm provides is a container for a collection of fields, which it will bind at instantiation , and hold in an internal dict. BaseForm提供的是一个字段集合的容器,它将在实例化时绑定,并保存在内部字典中。 Dict-style access on a BaseForm instance will allow you to access (and modify) the enclosed fields. BaseForm 实例上的字典式访问将允许您访问(和修改)封闭的字段。

Then, when you create an instance of your ExampleForm() class, it'll bind the FormField field, which then in turn creates an instance of the nested form object, which then binds each of the fields you gave BaseForm()然后,当您创建ExampleForm()类的实例时,它将绑定FormField字段,然后该字段又会创建嵌套表单对象的实例,然后绑定您提供给BaseForm()每个字段

Because calling BaseForm(fields) will create a form instance , you do need to wrap that in a function first before you can use it as a nested form:因为调用BaseForm(fields)将创建一个表单实例,您需要先将其包装在一个函数中,然后才能将其用作嵌套表单:

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() doesn't take any data like a Form class would, so you need to pass the parameters that FormField() passes into create an instance to the .process() method before returning the instance. BaseForm()不像Form类那样接受任何数据,因此您需要在返回实例之前将FormField()传递给 create 实例的参数传递给.process()方法。

When iterating over the list_checkbox field when rendering, you get the fields directly and you get the label from the field object:渲染时迭代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>

Demo (using the base WTForms library, but the Flask-WTF process is the same): Demo(使用基础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">

The FormField() field then also makes sure that you can set default values for your form, or that you can then access the data set when the form is posted again:然后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">

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM