Passing a dictionary from pythonFlask to Jinja2, error keeps telling me variable is undefined

Overall my goal is to dynamically update a table in html with data from a dictionary passed through flask into a jinja loop.

In trying to populate an html table with data from a dictionary created in pythonFlask through passing it in a jinja2 loop, I continually get the error: “jinja2.exceptions.UndefinedError: ‘results’ is undefined”.

I’ve properly defined my dictionary in Flask, the return/render statement, and the jinja2 loop but for some reason it fails with an internal server error, claiming it is undefined.

My current code is as follows…

jinja2/html:

{% extends "hw12_home.html" %}
{% block header %} Word counter! {% endblock %}
{% block paragraph %} Type or paste any text in to count. {% endblock %}

{% block body %}

<form action="/wordCount" method="POST">
    <textarea name = "wordCount_text" rows = "20" cols = "125"></textarea> <br>
    <input type ="Submit" value = "Count Words!">
</form>

<table id = "word_table">
    <tr>
        <th> Word: </th>
        <th> Count: </th>
    </tr>

{% for key, value in results.items() %}
            <tr> <td> {{ key }} </td> <td> {{ value }} </td></tr>
{% endfor %}
    

</table>
{% endblock %}

pythonFlask:

@app.route('/wordCount' , methods= ['GET', 'POST'])
def wordCount ():
    
    if request.method == 'POST':
        
        wordCount_text = request.form['wordCount_text']
        wordCount_split = wordCount_text.split(' ')
        
        results = {}
        uniqueWords = []
        
        for word in wordCount_split:
            if word != '' and word not in uniqueWords:
                uniqueWords.append(word)
                results[word] = ""
        
        for word in uniqueWords:
            count = 0
            for word_2 in wordCount_split:
                if word == word_2:
                    count += 1
            results[word] = str(count)
       
        return render_template('word_count.html', results=results)
        
    return render_template('word_count.html')

I’ve tried the following in the jinja loop, .iteritems() , .itervalues()

I’ve looked at multiple solutions on stack and even web resources that show syntax that mimics my setup , but for some reason ‘results’ is still being shown as undefined.

I know my dictionary is setup with the results I expect thanks to this test print statement:
enter image description here

I’ve also tried passing the dictionary in the return/render statement like this and that didn’t work either:
enter image description here

I’m expecting a table that looks like this…
enter image description here

Originally I attempted it with two lists and a nested jinja2 for loop, but the nested loop would complete its iterations before breaking out and continuing to include the data from the first loop, resulting in a table that looked like this:

enter image description here

my jinja/html code for this attempt looked like this:

{% for i in uniqueWords %}
    <tr> <td> {{ i }} </td>
        {% for j in countList %}
            <td> {{ j }} </td> </tr>
        {% endfor %} 
    {% endfor %}

Overall, I can’t figure out why i’m being told results is undefined.

Thanks for any suggestions in advance.

Your wordCount() view has two return statements. One when the method is POST and another one when its a GET. When its a GET you are not passing anything to the variable results which is why you are getting results is undefined. There are two ways you can solve this:

  • You could pass an empty dictionary to the template when the method is GET so is not undefined.
@app.route('/wordCount' , methods= ['GET', 'POST'])
def wordCount ():
  if request.method == 'POST':
    #...
    return render_template('word_count.html', results=results)

  return render_template('word_count.html', results={})
  • or in jinja2 you can check first whether a variable is defined or not. {% if variable is defined %} so in your template word_count.html the loop should be wrapped by the if condition.
{% if results is defined %}
{% for key, value in results.items() %}
    <tr> <td> {{ key }} </td> <td> {{ value }} </td></tr>
{% endfor %}
{% endif %}

Leave a Comment