57

There is form with two <input type="submit">. But when i'm sending it, second submit causes error.

layout:

<form action="{{ url_for('index') }}" method="post">
    <input type="submit" name="add" value="Like">
    <input type="submit" name="remove" value="Dislike">
</form>

main.py:

...
if request.method == 'POST':
    if request.form['add']:
        return redirect(url_for('index'))
    elif request.form['remove']:
        return redirect(url_for('index'))
...

First submit(add) works well, but second(remove)...:

Bad Request The browser(or proxy) sent a request that this server could not understand.

How can i fix this error?

UPD:

It was pretty simple: request.form returns ImmutableMultiDict:

... 
if 'Like' in request.form.values():
     ...
elif 'Dislike' in request.form.values():
     ...
Dmitrijs Zubriks
  • 2,696
  • 6
  • 22
  • 33

3 Answers3

90

As @Blubber points out, the issue is that Flask raises an HTTP error when it fails to find a key in the args and form dictionaries. What Flask assumes by default is that if you are asking for a particular key and it's not there then something got left out of the request and the entire request is invalid.

There are two other good ways to deal with your situation:

  1. Use request.form's .get method:

    if request.form.get('add', None) == "Like":
        # Like happened
    elif request.form.get('remove', None) == "Dislike":
        # Dislike happened
    
  2. Use the same name attribute for both submit elements:

    <input type="submit" name="action" value="Like">
    <input type="submit" name="action" value="Dislike">
    
    # and in your code
    if request.form["action"] == "Like":
        # etc.
    
Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • I was using "id" in the template and it was throwing the 400 bad request error. Then I changed that to "name" and the request is accepted now. Thank you – Cognoscis Dec 21 '15 at 13:57
  • 2
    This behaviour is kind of unexpected. Would've at least hoped for a log line or a traceback. – ffledgling Jul 26 '16 at 12:30
  • 1
    @ffledgling There is a security concern if error messages are too informative. Still I'd have appreciated something less cryptic in the error logs. I keep relearning what 400 BAD REQUEST means in Flask. – Bob Stein Sep 26 '16 at 19:54
4

You should be checking whether or not the 'add' and 'remove' keys are in the request.form dict.

if request.method == 'POST':
    if 'add' in request.form:
        return redirect(url_for('index'))
    elif 'remove' in request.form:
        return redirect(url_for('index'))

When you click Like it doesn't fail because the first condition is met, and hence the second is never checked. But if the Dislike button is clicked, that first condition will thrown a KeyError exception because request.form doesn't contain a key named 'add'.

davidism
  • 121,510
  • 29
  • 395
  • 339
Blubber
  • 2,214
  • 1
  • 17
  • 26
  • 4
    There's not any other errors, although debug mode is on. I've tried your variant, however there's an error again: 400 Bad Request. – Dmitrijs Zubriks Dec 18 '11 at 15:49
  • I assume you are running Flask behind a proxy? Are you sure there is no exception in the terminal (or wherever you started your application)? – Blubber Dec 18 '11 at 16:29
  • 1
    No, i'm not running Flask behind a proxy. I'v tried try/except block: 400: Bad Request. There's no any another exception in terminal. I'v also tried to make two forms with one submit button in each, but the result is same: second submit causese 400 error. – Dmitrijs Zubriks Dec 18 '11 at 16:32
  • 1
    There are no other errors in that situation. No traceback. Just that "less useless" output. – a.m. Feb 06 '13 at 12:48
0

Instead of <input type="submit"> Use <button type="submit">. I have the same error as you and tried soo many solution but none of that work

MEET SHAH
  • 93
  • 1
  • 7