【问题标题】:Can I make dependent select box populated through Jinja variables?我可以通过 Jinja 变量填充依赖选择框吗?
【发布时间】:2019-12-01 09:50:54
【问题描述】:

我正在使用带有 Jinja2 模板的 Flask,如何使用 Jinja2 或使用 Java 脚本 + Jinja2 变量制作依赖选择 pox?

示例:

Python 端:

@app.route('/')
def dependent():
    cars= {'Chevrolet':['Volt','Malibu','Camry'],'Toyota':['Yaris','Corolla'],'KIA':['Cerato','Rio']}
    return render_template('select.html',cars=cars)

HTML+Jinja 方面

<form>
<select name="car_vendor" id="car_vendor">
    {% for key, value in cars.items() %}
        <option value="{{ key }}"> {{ key }} </option>
    {% endfor %}
</select>


<select name="car_model" id="car_model">
    ---
    ---
</select>
</form>

如何根据 car_vendor 选择框填充 car_model 选择框,如图所示:

PS:我对 JS、jQuery 和 Ajax 完全一无所知,我见过很多 JS 或 jQuery 示例,我就像一个在沙漠中迷失和瘫痪的人,所以如果你要帮忙,请编辑我的代码示例,不要将我链接到外部链接。提前致谢。

【问题讨论】:

    标签: javascript python jinja2


    【解决方案1】:

    首先,您需要指定已选择的汽车供应商和型号,以确定应如何填充相关选择框:

    cars = {'Chevrolet':['Volt','Malibu',Camry],'Toyota':['Yaris','Corolla'],'KIA':['Cerato','Rio']}
    return render_template('select.html',cars=cars, selected_car='Toyota', selected_model = 'Prius')
    

    其次,对于第一个选择框,您应该只枚举 keys 而不是 items,因为您不需要使用字典的值。你在做什么“有效”,但不太清楚。您应该设置已选择选项的selected 属性:

    <select name="car_vendor" id="car_vendor">
        {% for key in cars.keys() %}
            <option value="{{ key }}" {% if key == selected_car %}selected="selected"{% endif %}> {{ key }} </option>
        {% endfor %}
    </select>
    

    最后,被选中的汽车模型决定了用哪组模型填充依赖选择框:

    <select name="car_model" id="car_model">
        {% for model in cars[selected_car] %}
            <option value="{{ model}}" {% if model == selected_model %}selected="selected"{% endif %}> {{ model}} </option>
        {% endfor %}
    </select>
    <form>
    

    现在上面假设总是选择汽车和汽车型号。您可能一开始没有选择selected_carselected_model 都是None。为了支持这一点,第一个选择框应该有一个初始标签:

    <option value=''>*** Select a car make ***</option>
    

    如果没有其他选项作为selected 属性集,则默认选择此选项。 (您可以并且应该向第二个选择框添加类似的选项。)由于 selected_carNone,因此您需要在第二个选择框周围进行测试:

    {% if selected_car %}
        <select name="car_model" id="car_model">
        etc.
    {% endif %}
    

    所以在第一个框中有选择之前,第二个文本框不会显示。

    但是您必须始终确保当第一个框中的选择发生更改时,表单已提交并且新的选择可以反映在第二个框中。因此您需要添加到第一个选择框:

    <form name="f">
        <select name="car_vendor" id="car_vendor" onchange="document.f.submit();">
    

    更新:示例流程

    1. 首次调用服务器端脚本时,既没有设置表单变量car_vendor,也没有设置car_model。因此,模板在模板变量selected_carselected_model 都设置为None 的情况下被调用。这会导致汽车供应商选择框被填充而没有选择,并且汽车型号选择框不会显示。
    2. 用户从汽车供应商选择框中选择丰田。应该安排,每当从该框中进行选择时,如果正在显示车型框,则在提交表单之前首先清除所有车型选择。
    3. 表单被提交到服务器端脚本,表单变量car_vendor设置为'Toyota'并且car_model未设置,因此模板变量selected_car设置为Toyotaselected_model设置为None。这会导致车型选择框将丰田显示为当前选择的车型,并且车型选择框会显示所有丰田车型,但没有当前选择。
    4. 用户现在在汽车供应商选择框中选择雪佛兰。因为正在显示汽车型号选择框,所以在提交表单之前,应首先清除它的任何选择(目前没有)。
    5. 表单被提交到服务器端脚本,表单变量car_vendor设置为'Chevrolet'和car_model未设置,因此模板变量selected_car设置为Chevroletselected_model设置为None。这会导致车型选择框将雪佛兰显示为当前选择的车型,并且车型选择框会显示所有雪佛兰车型,但没有当前选择。
    6. 用户从车型选择框中选择凯美瑞。
    7. 表单被提交到服务器端脚本,表单变量car_vendor设置为“雪佛兰”,car_model设置为“凯美瑞”,因此模板变量selected_car设置为Chevroletselected_model id 设置为Camry。这导致车型选择框显示雪佛兰​​作为当前选择的汽车,并且车型选择框显示所有雪佛兰车型和“凯美瑞”作为当前选择。此外,既然已经选择了供应商和模型,则执行任何处理和输出。请注意,现在如果选择了新的供应商,在提交表单之前将首先取消选择当前模型,以确保属于不同供应商的模型不会与表单一起发送。 这就是选择新车厂商时清除车型选择的原因。

    基于示例流程的示例代码(或多或少)

    from flask import Flask, request, render_template_string
    app = Flask(__name__)
    
    
    @app.route('/', methods=['POST', 'GET'])
    def dependent():
        cars = {'Chevrolet':['Volt','Malibu','Camry'],'Toyota':['Yaris','Corolla'],'KIA':['Cerato','Rio']}
        # look for data from form POST (won't be present when we are invoked with GET initially)
        selected_car = request.form['car_vendor'] if 'car_vendor' in request.form else None
        if not selected_car or selected_car not in cars:
            selected_car = None
            selected_model = None
        else:
            selected_model = request.form['car_model'] if 'car_model' in request.form else None
            # This is an alternative to unselecting the car model whenever a new car vendor is selected.
            # Instead, we just check whether the selected model belongs to the selected car vendor or not:
            if selected_model and selected_model not in cars[selected_car]:
                selected_model = None
        # Use a string template for demonstration purposes:
        return render_template_string("""
    <!DOCTYPE html>
    <html>
    <head>
    <title>Flask Demo</title>
    <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0">
    </head>
    <body>
    <h2>Select Car</h2>
    <form name="f" method="post">
      <table>
        <tr>
          <th>Make</th>
        <th>Model</th>
        </tr>
        <tr>
          <td>
            <select name="car_vendor" id="car_vendor" onchange="document.f.submit();">
    {% if not selected_car %}
              <option value=''>-- Select a Make --</option>
    {% endif %}
    {% for car in cars.keys() %}
              <option value="{{ car }}" {% if car == selected_car %}selected="selected"{% endif %}>{{ car }}</option>
    {% endfor %}
            </select>
          </td>
          <td>
    {% if selected_car %}
            <select name="car_model" id="car_model" onchange="document.f.submit();">
      {% if not selected_model %}
              <option value=''>-- Select a Model --</option>
      {% endif %}
      {% for model in cars[selected_car] %}
              <option value="{{ model }}" {% if model == selected_model %}selected="selected"{% endif %}>{{ model }}</option>
      {% endfor %}
            </select>
    {% endif %}
          </td>
        </tr>
      </table>
    </form>
    
    {% if selected_car and selected_model %}
    <p style="color: red;">Both make and model have been selected: {{ selected_car }} and {{ selected_model }}.</p>
    {% endif %}
    </body>
    </html>
    """, cars=cars, selected_car=selected_car, selected_model=selected_model)
    

    【讨论】:

    • 我已尝试按照您的步骤操作,但对我不起作用。我认为您可能会在回答中遗漏一些内容,这会让我越界:selected_car 如何根据第一个选择字段进行更新?现在 onchange 只是将任何响应改回“Toyota”。
    • 我用更详细的示例流程更新了答案。我期待着您在 2022 年的下一个问题。:-)
    • 感谢您的回复,我的道歉对您来说太早了:) 我想我了解操作顺序,我只是不清楚您如何将 car_vendor 的新值传递给服务器端脚本.我正在寻找这样的 Python 代码,'啊,现在我知道用户选择了什么'
    猜你喜欢
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 2013-04-10
    • 1970-01-01
    • 2011-01-23
    • 1970-01-01
    • 2016-04-16
    相关资源
    最近更新 更多