Flask App Using WTForms with SelectMultipleField
Solution 1
Flask returns request.form as a werkzeug MultiDict object. This is kind of like a dictionary, only with traps for the unwary.
http://flask.pocoo.org/docs/api/#flask.request http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.MultiDict
MultiDict implements all standard dictionary methods. Internally, it saves all values for a key as a list, but the standard dict access methods will only return the first value for a key. If you want to gain access to the other values, too, you have to use the list methods.
However, I think there's an easier way. Can you do me a favor and try replacing:
language = request.form['language']
with
language = form.language.data
and see if that's any different? WTForms should handle the MultiDict object and just return a list for you since you've bound form data to it.
Solution 2
I ran into this problem recently. I found that you can retrieve all the items selected using
request.form.getlist('...')
This evaluates to a list with all selected items in it. In your case, use:
languages = request.form.getlist('language')
Raj
Updated on July 19, 2022Comments
-
Raj almost 2 years
I have a Flask application that uses WTForms for user input. It uses a
SelectMultipleField
in a form. I can't seem to get the app to POST all items in the field when selected; it only sends the first item selected regardless of how many the user selects.The Flask documentation says this about the data sent from this field type, but I don't see this behavior:
The data on the SelectMultipleField is stored as a list of objects, each of which is checked and coerced from the form input.
Here's a complete, minimal Flask app that illustrates this:
#!/usr/bin/env python from flask import Flask, render_template_string, request from wtforms import Form, SelectMultipleField application = app = Flask('wsgi') class LanguageForm(Form): language = SelectMultipleField(u'Programming Language', choices=[('cpp', 'C++'), ('py', 'Python'), ('text', 'Plain Text')]) template_form = """ {% block content %} <h1>Set Language</h1> <form method="POST" action="/"> <div>{{ form.language.label }} {{ form.language(rows=3, multiple=True) }}</div> <button type="submit" class="btn">Submit</button> </form> {% endblock %} """ completed_template = """ {% block content %} <h1>Language Selected</h1> <div>{{ language }}</div> {% endblock %} """ @app.route('/', methods=['GET', 'POST']) def index(): form = LanguageForm(request.form) if request.method == 'POST' and form.validate(): print "POST request and form is valid" language = request.form['language'] print "languages in wsgi.py: %s" % request.form['language'] return render_template_string(completed_template, language=language) else: return render_template_string(template_form, form=form) if __name__ == '__main__': app.run(debug=True)