title: HTML range slider to Flask with AJAX call
body: <p>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.</p>
  <p>I cannot seem to get the slider controls to work, When I adjust the slider I get the following error:</p>
  <pre><code> werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
  KeyError: 'button'
  </code></pre>
  <p>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.</p>
  <p>I initially had the following HTML:</p>
  <pre><code>&lt;input id=&quot;slider&quot; type=&quot;range&quot; min=&quot;0&quot; max=&quot;100&quot; value=&quot;50&quot; onchange=&quot;updateVolume(getElementById('slider').value); return false;&quot;&gt;
  </code></pre>
  <p>Javascript:</p>
  <pre><code>&lt;script&gt;
          function updateVolume (vol) {
              $.ajax({
                  method: &quot;POST&quot;,
                  url: '{{ url_for('main.control_panel', video_id=video.id) }}',
                  data: { volume: vol}
              })
              .done(function( msg ) {
                  // optional callback stuff if needed
                  // alert( &quot;Data Saved: &quot; + msg );
              });
          }
  &lt;/script&gt;
  </code></pre>
  <p>This threw up the same error.</p>
  <p>This is my current code that also throws the same error:</p>
  <p>HTML:</p>
  <pre><code>&lt;input id=&quot;slide&quot; type=&quot;range&quot; min=&quot;1&quot; max=&quot;100&quot; step=&quot;1&quot; value=&quot;10&quot; name=&quot;slide&quot;&gt;
  &lt;div id=&quot;sliderAmount&quot;&gt;&lt;/div&gt;
  </code></pre>
  <p>Javascript:</p>
  <pre><code>var slide = document.getElementById('slide'),
      sliderDiv = document.getElementById(&quot;sliderAmount&quot;);
  
  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);
              }
          });
  }
  </code></pre>
  <p>Python:</p>
  <pre><code>@main.route(&quot;/control_panel/&lt;int:video_id&gt;&quot;, 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)
  </code></pre>
  <p>Any support would be greatly appreciated as I'm struggling to find solutions on the web along with me aforementioned js/ajax knowledge.</p>
  <p>Thanks</p>
  <p><strong>EDIT:</strong></p>
  <p>This is a recreation of the problem:</p>
  <p>python:</p>
  <pre><code>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(&quot;play button pressed&quot;)
  
          elif request.form['button'] == 'button-exit':
              print(&quot;exit button pressed&quot;)
  
          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)
  </code></pre>
  <p>HTML:</p>
  <pre><code>&lt;!doctype html&gt;
  &lt;html lang=&quot;en&quot;&gt;
    &lt;head&gt;
      &lt;!-- Required meta tags --&gt;
      &lt;meta charset=&quot;utf-8&quot;&gt;
      &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1, shrink-to-fit=no&quot;&gt;
  
      &lt;!-- Bootstrap CSS --&gt;
      &lt;link rel=&quot;stylesheet&quot; href=&quot;https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css&quot; integrity=&quot;sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk&quot; crossorigin=&quot;anonymous&quot;&gt;
  
      &lt;title&gt;Slider&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
      &lt;div class=&quot;container&quot; id=&quot;control_panel_1&quot;&gt;
    &lt;form action=&quot;/&quot; method =&quot;post&quot; enctype=&quot;multipart/form-data&quot; id=&quot;form&quot;&gt;
      &lt;div class=&quot;row&quot;&gt;
              &lt;div class=&quot;col&quot;&gt;
                &lt;button class=&quot;btn btn-primary&quot; button type=&quot;submit&quot; name=&quot;button&quot; value=&quot;button-play&quot;&gt;PLAY&lt;/button&gt;
  
                &lt;button class=&quot;btn btn-primary&quot; button type=&quot;submit&quot; name=&quot;button&quot; value=&quot;button-exit&quot;&gt;EXIT&lt;/button&gt;
  
                &lt;input id=&quot;slide&quot; type=&quot;range&quot; min=&quot;1&quot; max=&quot;100&quot; step=&quot;1&quot; value=&quot;10&quot; name=&quot;slide&quot;&gt;
                &lt;div id=&quot;sliderAmount&quot;&gt;&lt;/div&gt;
              &lt;/div&gt;
      &lt;/div&gt;
    &lt;/form&gt;
  
      &lt;!--- SCRIPTS ---&gt;
      &lt;script src=&quot;https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js&quot;&gt;&lt;/script&gt;
      &lt;script src=&quot;https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js&quot; integrity=&quot;sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo&quot; crossorigin=&quot;anonymous&quot;&gt;&lt;/script&gt;
      &lt;script src=&quot;https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js&quot; integrity=&quot;sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI&quot; crossorigin=&quot;anonymous&quot;&gt;&lt;/script&gt;
  &lt;/body&gt;
  &lt;script&gt;
    var slide = document.getElementById('slide'),
      sliderDiv = document.getElementById(&quot;sliderAmount&quot;);
  
  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);
              }
          });
  }
  &lt;/script&gt;
  &lt;/html&gt;
  </code></pre>