通过 Flask 中的查询字符串获取表单数据

Fetching form data through query string in flask

这是我的第一个问题,如果我遗漏了什么,请告诉我 ;)

我正在建立一个网站,该网站将 运行 一些 python 代码来解决特定问题并将结果显示为数字和图表(都在同一页面上)。为了在运行宁python代码之前使用参数并可视化它们,我首先需要将一些表单数据从html发送到flask,所以我想我可以通过ajax - 正如我之前所做的那样,根据 mpld3 示例使用标准参数绘制结果。

首先,html/表单端(查找评论):

<div class="row">
    <div class="col-md-8">
        <div class="panel panel-primary">
            <div class="panel-heading">
                <h3 class="panel-title">Context Plots</h3>
            </div>
            <div class="panel-body overflow">
                <div calss="loading-div" id="context_loading_div">
                    <div class="loading-tag">
                        <i class="fa fa-cog fa-spin"></i>
                    </div>
                </div>
                <div class="plot" id="context_plot_container"></div>
                <!-- ### plot script here ### -->
                <script src="{{ url_for('static', filename='js/solver_context.js') }}" type="text/javascript">
                </script>
            </div>
        </div>
    </div>

    <div class="col-md-4">
        <div class="panel panel-primary">
            <div class="panel-heading">
                <h3 class="panel-title">Context Parameters</h3>
            </div>
            <div class="panel-body">
                <form action="" method="post" class="form-horizontal">
                    <div class="form-group">
                        <label for="buy_upper" class="col-sm-6 control-label" title="Utility buying price low tariff">Buying high [CHF]</label>
                        <div class="col-sm-6 input-group">
                            <span class="input-group-addon"><i class="fa fa-usd"></i></span>
                            <--! ### form element to fetch data from here ### -->
                            <--! the jinja templating stuff here works fine -->
                            <input type="range" name="buy_upper" class="form-control" id="buy_upper" min="0.05" max="1.0" step="0.01" value={% if reqMeth == 'POST' %}{{ request.form['buy_upper'] }} {% else %}"0.22"{% endif %} />
                        </div>
                        <--! some more form elements -->
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>

二、javascript/ajax方:

$(window).load(function() {
    $("#context_plot_container").hide();
    $("#context_loading_div").show();
    var buy_upper = document.getElementById("buy_upper").value;
    var buy_lower = document.getElementById("buy_lower").value;
    var sell_upper = document.getElementById("sell_upper").value;
    var sell_lower = document.getElementById("sell_lower").value;
    var qu = {"buy_upper": buy_upper, "buy_lower": buy_lower, "sell_upper": sell_upper, "sell_lower": sell_lower};
    $.ajax({
        type: "POST",
        async: true,
        contentType: "application/json; charset=utf-8",
        url: "/context_plot",
        data: JSON.stringify(qu),
        success: function (data) {     
            var graph = $("#context_plot_container");
            graph.html(data);
            $("#context_plot_container").show();
            $("#context_loading_div").hide();
        },
        dataType: "html"
    });
});

此脚本应该 运行 在按下刷新按钮后,但现在我将它与页面的其余部分同时加载。由于我对 javascript/jquery/ajax 的任何事物都是新手,所以我或多或少只是复制了上面提到的 mpld3 示例。

最后,python/烧瓶方面:

## plot routes
@app.route('/context_plot', methods=['GET', 'POST'])
def context_plot():
    import numpy as np
    plt.close(); # (opened above - works fine in the results plot)

    # check params
    # try:
    buy_upper = float(request.args.get('buy_upper'));
    buy_lower = float(request.args.get('buy_lower'));
    sell_upper = -float(request.args.get('sell_upper'));
    sell_lower = -float(request.args.get('sell_lower'));
    # except:
    #     buy_lower = 0.19;
    #     buy_upper = 0.29;
    #     sell_lower = -0.09;
    #     sell_upper = -0.09;

    # data
    up = np.array([buy_lower] * 28 + [buy_upper] * 52 + [buy_lower] * 16);
    urp = np.array([sell_lower] * 28 + [sell_upper] * 52 + [sell_lower] * 16);

    # time vector
    t = np.arange(0, len(up) - 1, 1 / 96.0)[:len(up)];

    # figure
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize = (9, 6), sharex = 'col');
    # subplot 1
    ax1.grid(True, alpha = 0.5);
    ax1.set_ylabel('costs [CHF/kWh]');
    ax1.set_title('Utility profiles');
    ax1.plot(t, up, t, urp, 'k');
    ax1.margins(y = 0.1);
    leg = ax1.legend(['buying', 'selling'], loc = 'upper left', framealpha = 0);
    leg.set_title(''); # workaround for "None" at the bottom left
    # subplot 2
    ax2.grid(True, alpha = 0.5);
    ax2.plot(t, urp);
    ax2.margins(y = 0.1);

    plugins.connect(fig, plugins.MousePosition(fontsize=12));

    return mpld3.fig_to_html(fig); # (works fine in the results plot)

现在,当我尝试 运行 一切时,数字并没有出现。当我查看 firefox 的网络检查工具('Response' 部分)时,我发现 Werkzeugs 的调试器说:

File "X:\...\opt.py", line 84, in context_plot
    sell_upper = -1 * request.args.get('sell_upper');
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'

(来自 here

所以我的解释是查询字符串中没有 'sell_upper'。然后我再次查看 firefox 的网络检查工具('Params' 部分),我看到:

{"buy_upper":"0.99","buy_lower":"0.18","sell_upper":"0.27","sell_lower":"0.16"}

我还尝试通过使用 qu 而不是 JSON.stringify(qu) 或去掉引号等等来摆弄参数的传递方式......我似乎没有得到没错。

所以我想问题是查询字符串仍然格式不正确,或者 request.args.get() 在通过 ajax 调用路由时无法按预期工作,或者完全是别的东西-.-

您正在使用 AJAX 执行 POST 请求,但在 Flask 中访问 GET 请求参数(它们位于 url 的查询部分,以 [=11] 开头=]).看 Request object documentation.

您应该改用 form 属性。

 var = request.form.get('sell_upper')

如果响应可以被缓存并且除了在服务器上计算之外实际上不执行任何操作,您也可以在 AJAX 中简单地使用 GET 请求并保持 Python 代码不变。