【问题标题】:Display wtforms SelectMultipleField display as drop-down and not list显示 wtforms SelectMultipleField 显示为下拉列表而不是列表
【发布时间】:2022-01-03 09:44:16
【问题描述】:

我正在使用 wtforms SelectMultipleField 来呈现带有选项列表的表单。

使用普通的普通 SelectField 将选项呈现为下拉菜单 (dropdown)。

但是,我需要能够在列表中选择多个条目,因此想要使用 SelectMultipleField。但是,这会显示为一个列表框 (listbox)。

这是我的表单条目代码:test = SelectMultipleField('test', choices=[(1, 'a'), (2, 'b'), (3, 'c')])

要渲染的代码:<a class="test" id="test">{{ form.test }}</a>

如何渲染我的 SelectMultipleField 以显示为下拉列表?

【问题讨论】:

标签: python flask dropdown wtforms


【解决方案1】:

更新:找到“香草”解决方案!这里是:

A similar question was asked here。我拿了基础并将其调整为烧瓶/神社工作流程:

ma​​in.py:

from flask import Flask, render_template, request
from flask_wtf import FlaskForm
from wtforms.fields import SelectMultipleField, SubmitField
from wtforms import widgets

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


choices = [
    'apple',
    'banana',
    'cherry',
]


# This code from WTForms docs, this class changes the way SelectMultipleField
# is rendered by jinja
# https://wtforms.readthedocs.io/en/3.0.x/specific_problems/
class MultiCheckboxField(SelectMultipleField):
    """
    A multiple-select, except displays a list of checkboxes.

    Iterating the field will produce subfields, allowing custom rendering of
    the enclosed checkbox fields.
    """
    widget = widgets.ListWidget(prefix_label=False)
    option_widget = widgets.CheckboxInput()


class Form(FlaskForm):
    global choices
    select_multiple_field = MultiCheckboxField(choices=choices)
    submit = SubmitField()


@app.route('/', methods=['GET', 'POST'])
def index():
    form = Form()

    if request.method == 'POST':
        # Getting selected options
        form_data = form.select_multiple_field.data
        print(form_data)

    return render_template(
        'index.html',
        form=form,
    )


if __name__ == "__main__":
    app.run(debug=True)

index.html:

<!DOCTYPE html>
<html lang="en">

<head>
</head>

<body>

    <style>
        .dropdown-check-list {
            display: inline-block;
        }

        .dropdown-check-list .anchor {
            position: relative;
            cursor: pointer;
            display: inline-block;
            padding: 5px 50px 5px 10px;
            border: 1px solid #ccc;
        }

        .dropdown-check-list .anchor:after {
            position: absolute;
            content: "";
            border-left: 2px solid black;
            border-top: 2px solid black;
            padding: 5px;
            right: 10px;
            top: 20%;
            -moz-transform: rotate(-135deg);
            -ms-transform: rotate(-135deg);
            -o-transform: rotate(-135deg);
            -webkit-transform: rotate(-135deg);
            transform: rotate(-135deg);
        }

        .dropdown-check-list .anchor:active:after {
            right: 8px;
            top: 21%;
        }

        .dropdown-check-list ul.items {
            padding: 2px;
            display: none;
            margin: 0;
            border: 1px solid #ccc;
            border-top: none;
        }

        .dropdown-check-list ul.items li {
            list-style: none;
        }

        .dropdown-check-list.visible .anchor {
            color: #0094ff;
        }

        .dropdown-check-list.visible .items {
            display: block;
        }
    </style>

    <form action="{{ url_for('index') }}" method="POST">
        {{ form.hidden_tag() }}
        <div id="list1" class="dropdown-check-list" tabindex="100">
            <span class="anchor">Select Fruits</span>

            {{ form.select_multiple_field(class="items") }}

        </div>
        {{ form.submit }}
    </form>

    <script>
        var checkList = document.getElementById('list1');
        checkList.getElementsByClassName('anchor')[0].onclick = function (evt) {
            if (checkList.classList.contains('visible'))
                checkList.classList.remove('visible');
            else
                checkList.classList.add('visible');
        }
    </script>

</body>

</html>

===========================================

(这个依赖于一些 JQuery 库,但感觉与您正在寻找的内容很接近)

link to that library

ma​​in.py:

from flask import Flask, render_template, request
from flask_wtf import FlaskForm
from wtforms.fields import SelectMultipleField, SubmitField

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


choices = [
    'apple',
    'banana',
    'cherry',
]


class Form(FlaskForm):
    global choices
    select_multiple_field = SelectMultipleField(choices=choices)
    submit = SubmitField()


@app.route('/', methods=['GET', 'POST'])
def index():
    form = Form()

    if request.method == 'POST':
        # Getting selected options
        form_data = form.select_multiple_field.data
        print(form_data)

    return render_template(
        'index.html',
        form=form,
    )


if __name__ == "__main__":
    app.run(debug=True)

index.html:

<!DOCTYPE html>
<html lang="en">

<head>
    <link href="https://unpkg.com/multiple-select@1.5.2/dist/multiple-select.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
    <script src="https://unpkg.com/multiple-select@1.5.2/dist/multiple-select.min.js"></script>
</head>

<body>

    <style>
        select {
            width: 20%;
        }
    </style>

    <form action="{{ url_for('index') }}" method="POST">
        {{ form.hidden_tag() }}
        {{ form.select_multiple_field(**{"multiple": "multiple"}) }}
        {{ form.submit }}
    </form>

    <script>
        $(function () {
            $('select').multipleSelect({
                multiple: true,
                multipleWidth: 60
            })
        })
    </script>

</body>

</html>

===========================================

(如果这个答案不完全符合您的要求,请随时与我联系并说明原因,我会尝试调整它:D)

【讨论】:

  • 谢谢!这解决了我的问题。请注意,选择列表中有一个错误 - 需要是具有值和标签的元组列表:(1,'apples')。此外,第一个版本没有按应有的方式呈现 - 样式没有删除列表框。我还没有调试,因为 jquery 版本更适合我的设置,并且渲染得很好。在研究的过程中,我实际上实现了一个基于 select2 javascript lib 的不同版本。在此处查看文档:select2.org。现在我有两个选择——太好了! (因为我没有足够的声誉,所以无法支持​​这个答案......)
猜你喜欢
  • 2019-08-25
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
  • 2018-11-22
  • 2021-08-21
  • 2015-05-22
  • 1970-01-01
  • 2019-07-12
相关资源
最近更新 更多