Python 3.x 让Flask更改HTML下拉列表中的选定值

Python 3.x 让Flask更改HTML下拉列表中的选定值,python-3.x,flask,Python 3.x,Flask,我正在为家庭供暖控制系统编写一个原型前端,当用户从下拉框中选择房间和一周中的某一天时,我希望能够查询Redis数据库,检索当前设置的每小时温度,并使用它在温度下拉框中设置所选值。然后,用户可以更改一个或多个值并提交它们。我有提交和写的工作,只是想让我的头周围设置选定的 以下是HTML: {% extends "bootstrap/base.html" %} {% block title %}Setting Room Temperatures{% endblock %} {% block navb

我正在为家庭供暖控制系统编写一个原型前端,当用户从下拉框中选择房间和一周中的某一天时,我希望能够查询Redis数据库,检索当前设置的每小时温度,并使用它在温度下拉框中设置所选值。然后,用户可以更改一个或多个值并提交它们。我有提交和写的工作,只是想让我的头周围设置选定的

以下是HTML:

{% extends "bootstrap/base.html" %}
{% block title %}Setting Room Temperatures{% endblock %}
{% block navbar %}
<div class="navbar navbar-fixed-top">
  <!-- ... -->
</div>
{% endblock %}
{% block content %}
</head>
<body>
<h1>Room temperature configuration</h1>
<form action="{{ url_for('heating_config_form')}}" method="post" class="form-inline"> 
<div class="form-group">
<label for="roomselect">Room:</label>
<select class="form-control" name="roomselect">
  <option value="dining">Dining</option>
  <option value="kitchen">Kitchen</option>
  <option value="lounge">Lounge</option>
  <option value="study">Study</option>
 </select>
</div>
<br>
<br>
<div class="form-group">
<label for="dayselect">Day  :</label>
<select class="form-control" name="dayselect">
  <option value="monday">Monday</option>
  <option value="tuesday">Tuesday</option>
  <option value="wednesday">Wednesday</option>
  <option value="thursday">Thursday</option>
  <option value="friday">Friday</option>
  <option value="saturday">Saturday</option>
  <option value="sunday">Sunday</option>
</select>
</div>
<br>
<br>
 <div class="form-group">
 <label for="1AM">1AM :</label>
 <select class="form-control" name="1AM">
   <option value="5">5</option>
   <option value="6">6</option>
</select>
<label for="2AM">2AM :</label>
<select class="form-control" name="2AM">
  <option value="5">5</option>
  <option value="6">6</option>
</select>
</div>
<br>
<br>
<button type="submit" value="submitted" name="update">Update temperature </button><br>
<br>
</form>
<br>
</body></html>
{% endblock %}<html><head>
我知道可能有更好的方法来实现这一点(WTForms?),但我想获得一个我理解的简单设置界面,这样我就可以在开发更好的前端的同时对系统进行原型化,因为我对Flask是新手,不希望整个加热系统依赖于我的能力:)

将温度添加到数据库工作正常,这是redis cli监视器的典型监视器输出

127.0.0.1:6379> monitor
OK
1482336847.287342 [0 127.0.0.1:34180] "HSET" "kitchen_tuesday" "1:00" "5"
1482336847.288042 [0 127.0.0.1:34180] "HSET" "kitchen_tuesday" "2:00" "5"
我在想,也许下面的上下文处理器会有所帮助

@app.context_processor
def utility_processor():
    def retrieve_temp(sroom, sday, stime):
        skey= (sroom + "_" + sday)
        stemp = db.hget(skey, stime)
        return stemp
    return dict(retrieve_temp=retrieve_temp)
这将使函数retrieve_temp可用于所有模板-我想

然后,在渲染模板后,将使用默认的“房间和日期”在“时间”下拉列表中设置“选定”选项,然后每次移动“房间”和“日期”下拉列表时,同样的情况再次发生


因此,如果默认设置为“用餐”和“星期一”,则会检索凌晨1点和凌晨2点的温度,并将其设置为这些下拉列表中的“已选择”(次数更多,临时次数更多,为简洁起见,已将其删除)。如果房间和/或日期发生变化,它会再次发生。

好的-所以在我给您提供解决问题的信息之前,我只想确定您的问题。您在评论中概述的作为备选方案的方法是实现此目标的最简单方法(例如,进行第一次选择的中间页面)

重要的是要记住,任何python或jinja2代码只执行一次。Jinja2使用一些逻辑来呈现HTML输出,然后Flask向浏览器响应一个静态HTML页面,因此您可以使用
context\u处理器
将特定逻辑传递给Jinja2,但一旦Flask呈现页面,任何交互都需要由javascript管理

看起来您正在使用引导,它包括
jQuery
javascript库
jQuery
非常棒(在我看来),因为它可以为您处理一些与DOM交互和操作方面的浏览器怪癖(例如,文档对象模型、javascript对HTML元素的表示)

因此,如果要动态填充第二个select,可以设计一些代码来异步(例如,无需再次发出HTTP请求或“重新加载”页面)将数据从浏览器发送到Flask端点,以获取所需的选项,然后更新前端。我给你举个例子:

HTML看起来是这样的(我只是在添加ID。假定
for
标记引用的是ID字段,而不是名称,并且它还使javascript选择更容易):


哈…结果比我预期的要长一点,但这至少应该为你提供一个稻草人,让这样的功能发挥作用。Javascript无疑提供了更好的用户体验,但通过使用一系列填充静态页面的中间表单,您通常可以完成同样的任务。

好的-在我向您提供解决问题的信息之前,我只想确定您的问题。您在评论中概述的作为备选方案的方法是实现此目标的最简单方法(例如,进行第一次选择的中间页面)

重要的是要记住,任何python或jinja2代码只执行一次。Jinja2使用一些逻辑来呈现HTML输出,然后Flask向浏览器响应一个静态HTML页面,因此您可以使用
context\u处理器
将特定逻辑传递给Jinja2,但一旦Flask呈现页面,任何交互都需要由javascript管理

看起来您正在使用引导,它包括
jQuery
javascript库
jQuery
非常棒(在我看来),因为它可以为您处理一些与DOM交互和操作方面的浏览器怪癖(例如,文档对象模型、javascript对HTML元素的表示)

因此,如果要动态填充第二个select,可以设计一些代码来异步(例如,无需再次发出HTTP请求或“重新加载”页面)将数据从浏览器发送到Flask端点,以获取所需的选项,然后更新前端。我给你举个例子:

HTML看起来是这样的(我只是在添加ID。假定
for
标记引用的是ID字段,而不是名称,并且它还使javascript选择更容易):


哈…结果比我预期的要长一点,但这至少应该为你提供一个稻草人,让这样的功能发挥作用。Javascript无疑提供了更好的用户体验,但通常可以通过一系列填充静态页面的中间表单来完成同样的任务。

为了澄清……您希望有一组选择框,其中第二个仅显示基于第一个选择的值?每次第一个框中的选择发生变化时,您都希望ping数据库以获得适当的选择来填充第二个选择?这是一个公平的摘要PJ。用户选择房间和日期后,将从该房间/日期组合的数据库中检索每个小时的相应温度设置,并填充相应的下拉选择。例如,如果用户选择Lounge和Tuesday,则数据库将查询当天每小时的所有当前温度设置,以便可以为thos设置选择
@app.context_processor
def utility_processor():
    def retrieve_temp(sroom, sday, stime):
        skey= (sroom + "_" + sday)
        stemp = db.hget(skey, stime)
        return stemp
    return dict(retrieve_temp=retrieve_temp)
<div class="form-group">
    <label for="roomselect">Room:</label>
    <select class="form-control" name="roomselect" id="roomselect">
        <option value="dining">Dining</option>
        <option value="kitchen">Kitchen</option>
        <option value="lounge">Lounge</option>
        <option value="study">Study</option>
    </select>
</div>

<div class="form-group">
    <label for="dayselect">Day:</label>
    <select class="form-control" name="dayselect" id="dayselect">
        <option value="monday">Monday</option>
        <option value="tuesday">Tuesday</option>
        <option value="wednesday">Wednesday</option>
        <option value="thursday">Thursday</option>
        <option value="friday">Friday</option>
        <option value="saturday">Saturday</option>
        <option value="sunday">Sunday</option>
    </select>
</div>

<div class="form-group">
    <label for="1AM">1AM:</label>
    <select class="form-control" name="1AM" id="1AM">
        <option value="5">5</option>
        <option value="6">6</option>
    </select>
    <label for="2AM">2AM:</label>
    <select class="form-control" name="2AM" id="2AM" disabled>
        <option value="5">5</option>
        <option value="6">6</option>
    </select>
</div>
<script charset="utf-8" type="text/javascript">
    // this is called a javascript closure. it also wont run the code until the page is finished loading
    // and it protects the scope of your variables from other code you may later add to the page
    $(function() {
        var select_room = $('#roomselect'),
            select_day = $('#dayselect'),
            select_1am = $('#1am'),
            select_2am = $('#2am');

        select_room.on('change', function() {
            // fires when room selection changes
            getUpdatedSettings();
        });

        select_day.on('change', function() {
            // fires when day selection changes
            getUpdatedSettings();
        });

        function getUpdatedSettings() {
            // data to send back to the server
            var send = {
                room: select_room.val(),
                day: select_day.val()
            };

            // make the selections disabled while fetching new data
            select_1am.attr('disabled', true);
            select_2am.attr('disabled', true);

            $.getJSON("/_get_updated_settings", send, function(response) {
                // this send the room and the day select vals to the URL specified
                // we will need to add a handler for this in Flask

                // for the purpose of the example I am assuming the response will be
                // a JSON object that has a dictionary of elements ("am_1" and "am_2")
                // each of which is a list of values for the selects....

                console.log(response); // good for QA!

                // populate 1am
                select_1am.empty();
                $.each(response.am_1, function (index, value) {
                    select_1am.append(
                    $('<option>', {
                        value: value,
                        text: value
                    }, '</option>'))
                });

                // populate 2am
                select_2am.empty();
                $.each(response.am_2, function (index, value) {
                    select_2am.append(
                    $('<option>', {
                        value: value,
                        text: value
                    }, '</option>'))
                });

                // remove disabled now
                select_1am.removeAttr('disabled');
                select_2am.removeAttr('disabled');
            });
        }

    });
</script>
from flask import jsonify

@app.route('/_get_updated_settings')
def get_updated_settings():
    # good for debug, make sure args were sent
    print request.args
    day = request.args.get('day', 'default_if_none')
    room = request.args.get('room', 'default_if_none')
    key = (room + "_" + day)
    output = {}
    # I have no idea what this returns...just doing a list generator here assuming we get a list of values
    output['am_1'] = [x for x in db.hget(skey, '1am')]
    output['am_2'] = [x for x in db.hget(skey, '1am')]
    return jsonify(output)