繁体   English   中英

带有 BooleanField 的 Flask WTForms FieldList

[英]Flask WTForms FieldList with BooleanField

我想生成带有复选框的文件列表。 我尝试使用 FieldList 但它没有按我预期的那样工作。 我得到的不是带有指定文件名的复选框,而是带有以包含 FieldList 对象的变量命名的标签的复选框。 有什么办法可以解决吗?

应用程序.py:

from flask import Flask, render_template
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from wtforms import BooleanField, FieldList, SubmitField

app = Flask(__name__)
app.config['SECRET_KEY'] = 'development'
Bootstrap(app)

filenames = ['1.jpg', '2.jpg', '3.jpg', '4.jpg']


class FileListForm(FlaskForm):
    filename = FieldList(BooleanField(), 'Files')
    submit = SubmitField('Submit')


@app.route('/')
def listfiles():
    form = FileListForm()
    for filename in filenames:
        form.filename.append_entry(filename)
    return render_template('index.html',
                           form=form)


if __name__ == '__main__':
    app.run(debug=True, port=5001)

模板/index.html

{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}

包:

click==6.7
dominate==2.3.1
Flask==0.12.2
Flask-Bootstrap==3.3.7.1
Flask-WTF==0.14.2
itsdangerous==0.24
Jinja2==2.9.6
MarkupSafe==1.0
visitor==0.1.3
Werkzeug==0.12.2
WTForms==2.1

根据文档,WTForms 的FieldList不应与BooleanField一起使用:

注意:由于 HTML 发送值方式的限制, FieldList不能包含BooleanFieldSubmitField实例。

(即使 HTML 输出看起来有效。)也就是说,您没有看到您期望看到的内容,因为append_entry的第一个参数接受表单输入的值,而不是其标签。

相反,我建议动态创建表单类:

filenames = ['1.jpg', '2.jpg', '3.jpg', '4.jpg']

class FileListFormBase(FlaskForm):
    submit = SubmitField('Submit')

def file_list_form_builder(filenames):
    class FileListForm(FileListFormBase):
        pass

    for (i, filename) in enumerate(filenames):
        setattr(FileListForm, 'filename_%d' % i, BooleanField(label=filename))

    return FileListForm()

@app.route('/')
def listfiles():
    form = file_list_form_builder(filenames)
    return render_template('index.html', form=form)

注意:默认的 HTML 表示将在顶部有“提交”按钮,因为库按照定义的顺序呈现字段。 WTForms 本身不支持排序,所以这对你来说可能是一个更好的解决方案,即使它不太优雅:

filenames = ['1.jpg', '2.jpg', '3.jpg', '4.jpg']

def file_list_form_builder(filenames):
    class FileListForm(FlaskForm):
        pass

    for (i, filename) in enumerate(filenames):
        setattr(FileListForm, 'filename_%d' % i, BooleanField(label=filename))

    setattr(FileListForm, 'submit', SubmitField('Submit'))
    return FileListForm()

@app.route('/')
def listfiles():
    form = file_list_form_builder(filenames)
    return render_template('index.html', form=form)

如果这对将来的任何人有帮助。 这就是我实现此解决方案的 jinja 部分的方式。

我创建了一个要发送到模板的变量名称列表。 就我而言,我需要根据计数动态创建多个字段。 这些名称需要与您在构建表单时创建的名称相匹配,例如在上面针对此给定问题的选定解决方案中。

variable_names_list = []
for i in range(1, count+1):
    variable_names_list.append([f'var1_name_{i}',f'var2_name_{i}',f'var3_name_{i}',f'var4_name_{i}'])

将此发送到您的渲染模板语句中的模板然后使用以下 jinja 来显示您的表单项

                    <div class="row">
                        <table class="table table-bordered">
                            <tbody>
                                {{ form.csrf_token }}
                                {% for variable_names in variable_names_list %}
                                <tr>
                                    {% for variable in variable_names %} 
                                        <td>
                                            {{ form[variable] }}
                                        </td>
                                    {% endfor %}
                                </tr>

                                {% endfor %}
                            </tbody>

                        </table>
                    </div>

此解决方案的关键部分是这一行:

{{ form[variable] }}

我花了一段时间才弄清楚这是如何单独访问表单项的。

希望这对未来的人有所帮助。

干杯

暂无
暂无

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

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