Home > Net >  werkzeug.exceptions.BadRequestKeyError with forms with only buttons
werkzeug.exceptions.BadRequestKeyError with forms with only buttons

Time:03-14

I am trying to make my job easier by making a flask app that logs good parts, bad parts (with scrap codes), missing parts and time variables.

I have multiple "buttons" on a page that holds the log. I am currently trying to get the page to reload with current button states and store a timestamp (in the python script) when each specific button is pressed.

i.e. I click the start button, the page reloads with all checkmarks and button states in tact and stores a startTime stamp in the script for later use then disables the start button. If I click the pause button the page reloads with all data and state disabling the pause button and disabling the stop button until the pause button is clicked again (storing timestamps in script). If I click the stop button the results page will load showing all the totals in a formatted manner.

I have searched, reached out, debugged, used developer tools. One minute it works, the next it crashes. Currently, the home page will load and the start button works and disables. When I click stop, it crashes.

Traceback (most recent call last)
File "\dev\furnace-log\__init__.py", line 115, in home
if request.method == 'POST' and request.form['startTime'] == 'Start':
File "\dev\furnace-log\venv\Lib\site-packages\werkzeug\datastructures.py", line 377, in __getitem__
raise exceptions.BadRequestKeyError(key)
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'startTime'

This is the code for the buttons and forms. Note that some of the "if" statements for jinja are removed in the form.

<form method="post">
          {% if startBtnClicked == 1 %}
            <input  href="{{url_for('home')}}" type="submit" name="startTime" value="Start" disabled>
          {% else %}
            <input  href="{{url_for('home')}}" type="submit" name="startTime" value="Start">
          {% endif %}
          <input  href="{{url_for('home')}}" type="submit" name="pauseTime" value="Pause">
          <input  href="{{url_for('home')}}" type="submit" name="stopTime" value="Stop">
        </form>

This is the code for the home route. I had it printing to console any data per if branch for reference.

@app.route('/home', methods=['GET', 'POST'])
def home():
    form = LogNavButtons(request.form)
    # When Start is clicked the time is stored to DB after checking if Start has already been clicked
    if request.method == 'POST' and request.form['startTime'] == 'Start':
        # check if any bool is true or false
        if LogNavButtons.startActive == 0:
            # get the time the furncase started logging and set startActive to true(1)
            tm = time.time()
            LogNavButtons.startActive = 1
            flash('Now logging time and labels...', 'success')
            print(tm, LogNavButtons.startActive,
                  LogNavButtons.stopActive, LogNavButtons.pauseActive)
            # disable start button (show/inactive)
            # set Stop and Pause to false (show/active)
            return redirect(url_for('home'))
    # check to see if the Pause button was pressed
    elif request.method == 'POST' and request.form['pauseTime'] == 'Pause':
        if LogNavButtons.pauseActive == 0:
            tm = time.time()
            print(tm, LogNavButtons.startActive,
                  LogNavButtons.stopActive, LogNavButtons.pauseActive)
            LogNavButtons.pauseActive = 1
        return redirect(url_for('home'))
    # check to see if the Stop button has been pressed
    elif request.method == 'POST' and request.form['endTime'] == 'Stop':
        if LogNavButtons.stopActive == 0:
            tm = time.time()
            print(tm, LogNavButtons.startActive,
                  LogNavButtons.stopActive, LogNavButtons.pauseActive)
            LogNavButtons.stopActive = 1
            flash('All logging and counts have stopped...', 'danger')
            print(tm, LogNavButtons.startActive,
                  LogNavButtons.stopActive, LogNavButtons.pauseActive)
        return redirect(url_for('home'))
    # if not, all else
    else:
        return render_template('home.html', title='Furnace Log', form=form)

I do not have enough cred to link in an image with markdown, but here is a link to the image of the home route when loaded properly. https://drive.google.com/file/d/1eCC_q_xJjGMObYVI_tJq6UJOePHCYgtj/view?usp=sharing

I appreciate your time, patience and instruction.

CodePudding user response:

The stack trace points the way. The question is why 'startTime' isn't in the request. The answer is that buttons aren't form fields. If you clicked the 'stopTime' button, 'startTime' won't get sent as part of the post.

One way forward is to note that request.form is a kind of dict, and change

if request.method == 'POST' and request.form['startTime'] == 'Start':

to

if request.method == 'POST' and request.form.get('startTime', '') == 'Start':
  • Related