Search code examples
pythonhtmlflaskrequest

How receive name and value attribute of button in Flask


I try to receive a name and value from button in Flask by request.form after clicked a Save or Search button. I get tuple from select and option but not for button. I wonder what I am doing wrong?

signup.html:

<form class="form-signin" action="" method="post">
  <div class="form-group">
    <label for="exampleFormControlSelect1">Choose</label>
    <select class="form-control" id="exampleFormControlSelect1" name="select">
      <option value="o1">o1</option>
      <option value="o2">o2</option>
      <option value="o3">o3</option>
    </select>
    <label type="button" id="search" name="search" value="Search" class="btn btn-lg btn-primary btn-block">Search</label>
    <label type="button" id="save" name="save" value="Save" class="btn btn-lg btn-primary btn-block">Save</label>
  </div>
</form>

Python code:

from flask import Flask, render_template, request
import json
from my_func import my_func

app = Flask(__name__)


@app.route('/')
@app.route('/', methods=['POST'])
def signUpUser():
    if request.method == 'POST':
        print(request.form)
        select = request.form['select']  
        dict_to_json = {'status': 'OK', 'select': select}
        if select == "my_func":
            result = my_func('my_input')
            dict_to_json['my_func'] = result
        return json.dumps(dict_to_json)
     return render_template('signup.html')


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

Javascript:

$(function () {
    $('#search').click(function () {
        $.ajax({
            url: '/',
            data: $('form').serialize(),
            type: 'POST',
            success: function (response) {
                console.log('success')
            }
        });
    });
});

And from this I receive: ImmutableMultiDict([('select', 'o1')]) but I expected: ImmutableMultiDict([('select', 'o1'),('search','Search')])


Solution

  • The post method will send you only the input fields (input, textarea, select, radio-buttons, etc).

    So, to do what you want, you would have to transform the label element, into an input element, and make it behave like a submit button.

    You can do so by doing:

    <form class="form-signin" action="" method="post">
      <div class="form-group">
        <label for="exampleFormControlSelect1">Choose</label>
        <select class="form-control" id="exampleFormControlSelect1" name="select">
          <option value="o1">o1</option>
          <option value="o2">o2</option>
          <option value="o3">o3</option>
        </select>
        <input type="submit" id="search" name="action" value="Search" class="btn btn-lg btn-primary btn-block"/>
        <input type="submit" id="save" name="action" value="Save" class="btn btn-lg btn-primary btn-block"/>
      </div>
    </form>
    

    Since you have the same name, you can access the info as response.form['action'] that will be or "Search" or "Save".

    Solving as you said:

    HTML:

    <form class="form-signin" action="" method="post">
      <div class="form-group">
        <label for="exampleFormControlSelect1">Choose</label>
        <select class="form-control" id="exampleFormControlSelect1" name="select">
          <option value="o1">o1</option>
          <option value="o2">o2</option>
          <option value="o3">o3</option>
        </select>
        <input type="button" id="search" name="action" value="Search" class="btn btn-lg btn-primary btn-block"/>
        <input type="button" id="save" name="action" value="Save" class="btn btn-lg btn-primary btn-block"/>
      </div>
    </form>
    

    JavaScript:

    $(function () {
        $('[name="action"]').click(function () {
            $.ajax({
                url: '/',
                data: $('form').serialize(),
                type: 'POST',
                success: function (response) {
                    $("where you want to insert").html(response)
                }
            });
        });
    });