Flask & WTForms: How to make a form with multiple submit buttons?

Digital picture Digital · Mar 18, 2016 · Viewed 25.7k times · Source

Imagine I need to build a travel planning form like this:

Going from [_Picadily_Circus____]
Going to [_Marylebone_____]
(Starting by) (Arriving by) [5]:[30][pm]

Both (Starting by) (Arriving by) are submit buttons. The example is artificial to show a two-button usecase so let's not discuss usability.

How do I do this with Flask and WTForms?

How to see which button was actually pressed?

Answer

pjcunningham picture pjcunningham · Mar 19, 2016

Your form's submit button's data value will be True if it was pressed. See very simple example below of a form with two submit buttons and a single input field.

from flask import Flask, render_template, flash
from flask.ext.wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired

app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'well-secret-password'


class MyForm(Form):
    name = StringField(label='Name', validators=[DataRequired()])
    starting = SubmitField(label='Starting')
    ending = SubmitField(label='Ending')


@app.route('/', methods=['GET', 'POST'])
def index():
    form = MyForm()

    if form.validate_on_submit():
        print "Starting data Value : {value}".format(value=form.starting.data)
        print "Ending data Value : {value}".format(value=form.ending.data)
        flash(
            "You submitted name {name} via button {button}".format(
                name=form.name.data,
                button="Starting" if form.starting.data else "Ending"
            )
        )

        return render_template('index.html', form=form)

    if form.errors:
        for error_field, error_message in form.errors.iteritems():
            flash("Field : {field}; error : {error}".format(field=error_field, error=error_message))

    return render_template('index.html', form=form)


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

Here's the template file index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    {% with messages = get_flashed_messages() %}
      {% if messages %}
        <ul class=flashes>
        {% for message in messages %}
          <li>{{ message }}</li>
        {% endfor %}
        </ul>
      {% endif %}
    {% endwith %}

    <form method="POST" action="{{ url_for('index') }}">
        {{ form.csrf_token }}

        {{ form.name.label }} {{ form.name(size=20) }}
        <br><br>
        {{ form.starting }}
        {{ form.ending }}

    </form>
</body>
</html>