如何根据另一个SelectField的数据动态更新SelectField?

3 投票
2 回答
6285 浏览
提问于 2025-04-18 06:51

我遇到了一点问题。让我给你简单介绍一下我做的事情:我创建了一个简单的表单,里面有两个下拉选择框、一个文件上传框和一个提交按钮。第一个下拉框会从数据库中获取选项(这个我已经完成了)。然后,根据用户在第一个下拉框中选择的内容,第二个下拉框会从数据库中填充相应的结果。我希望这个过程是在用户选择第一个下拉框的内容后自动发生的,也就是说,第二个下拉框能够动态更新,而不需要刷新页面。

整个流程大概是这样的:

  • 从第一个下拉框中选择客户名称(根据选择从数据库中拉取客户计划的列表,并在不刷新页面的情况下填充到第二个下拉框中)。
  • 在第二个下拉框中选择客户计划中的一个。
  • 使用文件上传框上传相关的PDF文件。
  • 点击提交按钮。

有没有人能给我指个方向?我在家里周末工作,所以没有连接到数据库。我已经创建了三个列表来进行测试。

我尝试过做类似这样的事情:

if form.sf_baclient.data == 'py':
    form.sf_clientplan.choices = list2
else:
    form.sf_clientplan.choices = list3

但这并没有实现实时更新。以下是HTML和视图的代码:

HTML

    <form action="{{ url_for('index') }}" method=post>
        {{ form.hidden_tag() }}
        <dl>
            {{ form.sf_baclient.label }}<br>
            {{ form.sf_baclient }}<br>

            {{ form.sf_clientplan.label }}<br>
            {{ form.sf_clientplan }}<br>

            {{ form.ff_pdf_upload.label }}<br>
            {{ form.ff_pdf_upload }}<br>

        </dl>
        {{ form.sb_submit }}
    </form>

视图

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

form = MyForm(request.form)

list1 = [('cpp', 'C++'), ('py', 'Python'), ('text', 'Plain Text')]
list2 = [('1', 'One'), ('2', 'Two'), ('3', 'Three')]
list3 = [('blue', 'Blue'), ('red', 'Red'), ('green', 'Green')]

form.sf_baclient.choices = list1
form.sf_baclient.choices.insert(0, ('', ''))

form.sf_clientplan.choices = list3
form.sf_clientplan.choices.insert(0, ('', ''))

if request.method == 'GET':
    return render_template('home.html', form=form)

elif request.method == 'POST':
    if form.sb_submit.data == True:
        message = form.sf_baclient.data
        # flash(message)

    return render_template('home.html', form=form, success=True)

2 个回答

0
if 'py' in form.sf_baclient.data:
    form.sf_clientplan.choices = list2
else:
    form.sf_clientplan.choices = list3

从逻辑上讲,它应该和你现在的做法差不多。我知道你想要的是实时更新,试着把它放在一个循环里,这个循环在form.sf_baclient.data有数据的时候就会启动。

4

大部分内容需要在客户端进行编写,也就是在用户的设备上处理。我最后是这么做的。如果有不清楚的地方,请告诉我。

在你的视图文件中创建一个路由和网址,用来处理数据。通常我会用一个下划线和“parse”这个词来开始这些命名。下面是示例。

@app.route('/_parse_data', methods=['GET'])
def parse_data():
    if request.method == "GET":

        # only need the id we grabbed in my case. 
        id = request.args.get('b', 0)
        new_list = _call_to_db(id)

        # When returning data it has to be jsonify'ed and a list of tuples (id, value) to populate select fields.
        # Example: [('1', 'One'), ('2', 'Two'), ('3', 'Three')]

    return jsonify(new_list)

你需要用javascript或者jquery来确定用户的选择。所以在我的javascript代码中,我写了这个。

    $('#sf_baclient').on('change', function() {

            $("#sf_clientplan").empty();

            baclient_name = $("#sf_baclient option:selected").text();
            baclient_id = $("#sf_baclient option:selected").val();

            # Sending variables containing selection info to parse_data function in python.
            # jQuery's builtin ajax functions make things super easy 

            # Calling that parse url and sending it arguments
            $.getJSON($SCRIPT_ROOT + '/_parse_data', {
                a: baclient_name,
                b: baclient_id

            # Function to get data returned from parse_data and populate the second select field. 
            }, function(data) {
                # Using jQuery to populate new entries we got from flask.
                var options = $("#sf_clientplan");
                $.each(data, function() {
                    options.append($("<option />").val(this).text(this));
                });

            });

撰写回答