RandallShane RandallShane - 1 month ago 6
Python Question

How do I populate a select tag with Flask?

I am trying to access a list of JSON objects (from mongo) in python to populate a dropdown list using flask templates. Subsequently, I need to access the selected item. I am having difficulty getting the list to populate. Here's my python code and template. Can anyone point me in the right direction? I have not been able to find good documentation on how to populate the dd list with these templates.

PYTHON:

@app.route('/page', methods=["GET", "POST"])
@login_required
def chooser():
# Option list returns a list of JSON objects
option_list = get_options(g.user)
# {u'_id': ObjectId('52a347343be0b32a070e5f4f'), u'optid': u'52a347343be0b32a070e5f4e'}

# for debugging, checks out ok
print option_list

# Get selected id & return it
if request.form['submit'] == 'Select':
optid = o.optid
resp = 'You chose: ', optid
return Response(resp)

return render_template('chooser.html')


HTML TEMPLATE:

{% extends "layout.html" %}
{% block content %}
<h2>Chooser<h2>
<h3><table><form action="" method="POST">
<td>
<label>Select :</label>
<select name="option" width="300px">
{% for o in option_list %}
<option name="{{ o.optid }}" SELECTED>{{ o.optid }}</option>
</select>
</td>
<td>
<input class="button1" type="submit" value="Select">
</td>
{% endfor %}
</form></table><h3>

</div>
{% endblock content %}

Answer

There are a few things wrong here:

First, when you call render_template('chooser.html'), you are never passing any arguments to the template rendering process. By default, Jinja2 does not error out if an attribute your reference is not found, so you get no error message. Basically, for the code in your template that looks like this:

{% for o in option_list %}
    ....
{% endfor %}

The innards of this for loop are never rendered because you never specify what option_list is. In this case, Jinja2 will just default it to an empty string, and then you are essentially looping over the characters of the empty string (which of course means the innards of the for-loop are never run).

So, you need to specify the template what the value of option_list is:

return render_template('chooser.html', option_list=option_list)

The other issue is that your HTML is going to be messed up due to where you've put your for loop:

<select name="option" width="300px">
{% for o in option_list %}
    <option value="{{ o.optid }}" SELECTED>{{ o.optid }}</option>
    </select>
</td>
<td>
    <input class="button1" type="submit" value="Select">
</td>
{% endfor %}

I think you wanted to do the following:

<select name="option" width="300px">
{% for o in option_list %}
    <option value="{{ o.optid }}" SELECTED>{{ o.optid }}</option>
{% endfor %}
</select>
</td>
<td>
    <input class="button1" type="submit" value="Select">
</td>

See the rendering part of the tutorial, or the Jinja2 documentation for more info.