HTML范围滑块可通过AJAX调用到Flask [英] HTML range slider to Flask with AJAX call

查看:54
本文介绍了HTML范围滑块可通过AJAX调用到Flask的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有各种按钮和滑块的HTML控制面板.所有按钮都可操作,并且单击后会发送发布请求,我的Python应用程序会收到该请求,然后执行功能.

I have a HTML control panel with various buttons and sliders. All of the buttons are operational and when clicked send a post request which my Python app receives and then executes functions.

我似乎无法使滑块控件正常工作,调整滑块时出现以下错误:

I cannot seem to get the slider controls to work, When I adjust the slider I get the following error:

 werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'button'

这是有希望的,因为至少我可以看到它尝试做某事而失败,这是迄今为止取得的最佳结果.我的JavaScript和AJAX知识有限,我需要一种解决方案,使滑块可以在python可以解释的任何onchange值上发布请求.

This is promising as at least I can see it trying to do something and failing, which is the best result achieved thus far. My javascript and AJAX knowledge is limited and I need a solution for the slider to POST request on any onchange value that python can then interpret.

我最初有以下HTML:

I initially had the following HTML:

<input id="slider" type="range" min="0" max="100" value="50" onchange="updateVolume(getElementById('slider').value); return false;">

JavaScript:

Javascript:

<script>
        function updateVolume (vol) {
            $.ajax({
                method: "POST",
                url: '{{ url_for('main.control_panel', video_id=video.id) }}',
                data: { volume: vol}
            })
            .done(function( msg ) {
                // optional callback stuff if needed
                // alert( "Data Saved: " + msg );
            });
        }
</script>

这引发了同样的错误.

这是我当前的代码,也会引发相同的错误:

This is my current code that also throws the same error:

HTML:

<input id="slide" type="range" min="1" max="100" step="1" value="10" name="slide">
<div id="sliderAmount"></div>

JavaScript:

Javascript:

var slide = document.getElementById('slide'),
    sliderDiv = document.getElementById("sliderAmount");

slide.onchange = function() {
    sliderDiv.innerHTML = this.value;
    $.ajax({
            url: '{{ url_for('main.control_panel', video_id=video.id) }}',
            data: $('form').serialize(),
            type: 'POST',
            success: function(response){
                console.log(response);
            },
            error: function(error){
                console.log(error);
            }
        });
}

Python:

@main.route("/control_panel/<int:video_id>", methods=['GET', 'POST'])
def control_panel(video_id):
    video = video.query.get_or_404(video_id)

    if request.method == 'POST':

         ... #IF ELIF for various button functions here 

        volume = request.form['slider']
        return json.dumps({'volume': volume})

    return render_template('/control_panel.html', title=video.video, video=video)

在我努力与我上面提到的js/ajax知识一起在网络上寻找解决方案的过程中,任何支持将不胜感激.

Any support would be greatly appreciated as I'm struggling to find solutions on the web along with me aforementioned js/ajax knowledge.

谢谢

这是问题的重演:

python:

from flask import Flask, request, redirect, url_for, render_template, json

app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def control_panel():
    if request.method == 'POST':
        if request.form['button'] == 'button-play':
            print("play button pressed")

        elif request.form['button'] == 'button-exit':
            print("exit button pressed")

        elif request.form['slider']:
            volume = request.form['slider']
            return json.dumps({'volume': volume})
            print(volume)

    return render_template('index.html')

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

HTML:

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

    <title>Slider</title>
  </head>
  <body>
    <div class="container" id="control_panel_1">
  <form action="/" method ="post" enctype="multipart/form-data" id="form">
    <div class="row">
            <div class="col">
              <button class="btn btn-primary" button type="submit" name="button" value="button-play">PLAY</button>

              <button class="btn btn-primary" button type="submit" name="button" value="button-exit">EXIT</button>

              <input id="slide" type="range" min="1" max="100" step="1" value="10" name="slide">
              <div id="sliderAmount"></div>
            </div>
    </div>
  </form>

    <!--- SCRIPTS --->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
</body>
<script>
  var slide = document.getElementById('slide'),
    sliderDiv = document.getElementById("sliderAmount");

slide.onchange = function() {
    sliderDiv.innerHTML = this.value;
    $.ajax({
            url: '/index.html',
            data: $('form').serialize(),
            type: 'POST',
            success: function(response){
                console.log(response);
            },
            error: function(error){
                console.log(error);
            }
        });
}
</script>
</html>

推荐答案

问题是因为 $('form').serialize()仅发送来自< input> 的值code>但不是来自< button> ,而是在Flask中检查 request.form ['button'] ,由于键 button ,它会引发错误字典 request.form 中不存在.

Problem is because $('form').serialize() sends only values from <input> but not from <button> but in Flask you check request.form['button'] and it raises error because key button doesn't exists in dictionary request.form.

您必须使用

request.form.get('button')

,然后当字典中不存在 button 时,它返回 None .

and then it returns None when button doesn't exists in dictionary

顺便说一句:

  • 您只有 @ app.route("/",...),因此AJAX必须发送到/,而不是/index.html

  • you have only @app.route("/", ...) so AJAX has to send to /, not to /index.html

return ...之后使用 print(volume) 是没有用的,因为 return 终止了功能

在Flask中,您可以使用 return jsonify(dict)代替 return json.dumps(dict),然后发送特殊的标头,然后JavaScript将其转换为对象,您可以获取 response.volume .使用 json.dumps(dict)将其作为html/text发送,您将不得不使用 JSON.parse(response).volume

in Flask you can use return jsonify(dict) instead of return json.dumps(dict) and then it sends special headers and JavaScript converts it to object and you can get response.volume. Using json.dumps(dict) it sends it as html/text and you would have to use JSON.parse(response).volume

在一个文件中工作代码(使用 template_render_string 而不是 template_render ),这样每个人都可以轻松地对其进行测试.

Working code in one file (using template_render_string instead of template_render) so everyone can easily test it.

from flask import Flask, request, redirect, url_for, render_template, json, render_template_string, jsonify

app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def control_panel():
    print('request.form:', request.form)
    
    if request.method == 'POST':
        if request.form.get('button') == 'button-play':
            print("play button pressed")

        elif request.form.get('button') == 'button-exit':
            print("exit button pressed")

        elif request.form.get('slide'):
            volume = request.form.get('slide')
            print('volume:', volume)
            #return jsonify({'volume': volume})
            return json.dumps({'volume': volume})

    print('render')
    return render_template_string('''<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

    <title>Slider</title>
  </head>
  <body>
    <div class="container" id="control_panel_1">
  <form action="/" method ="post" enctype="multipart/form-data" id="form">
    <div class="row">
            <div class="col">
              <button class="btn btn-primary" button type="submit" name="button" value="button-play">PLAY</button>

              <button class="btn btn-primary" button type="submit" name="button" value="button-exit">EXIT</button>

              <input id="slide" type="range" min="1" max="100" step="1" value="10" name="slide">
              <div id="sliderAmount"></div>
            </div>
    </div>
  </form>

    <!--- SCRIPTS --->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
</body>
<script>
  var slide = document.getElementById('slide'),
    sliderDiv = document.getElementById("sliderAmount");

slide.onchange = function() {
    sliderDiv.innerHTML = this.value;
    $.post({
            url: '/',
            data: $('form').serialize(),
            success: function(response){
                alert(response);
                alert(response.volume);             // works with jsonify()
                alert(JSON.parse(response).volume); // works with json.dumps()
                console.log(response);
            },
            error: function(error){
                alert(response);
                console.log(error);
            }
        });
}
</script>
</html>''')

if __name__ == '__main__':
    app.run(debug=True, use_reloader=False)

这篇关于HTML范围滑块可通过AJAX调用到Flask的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆