How to get a Python dict into an HTML template using Flask/Jinja2
Question: I'm trying to use a Python dict in an HTML file. The dictionary is passed to
the HTML template through the `render_template` function in Flask.

This is the format of the dict:

    
    
    dict1[counter] =  {
        'title': l.getTitle(),
        'url': l.getLink(),
        'img': l.getImg()
    }
    

Then in the HTML template in which I want to iterate through this dict:

    
    
    {% for l in result.iteritems() %}
    <div class="link">
                <a href="{{ l.url }}"> {{l.title}}</a>
                <img src="{{ l.img }}" width="100" height="100">
    </div>
    {% endfor %}
    

I don't know what the problem is, since there is no error log in Flask.


Answer: The problem is that you’re iterating over `iteritems()`, which is an iterator
of (key, value) pairs. This means that the `l` variable is a tuple, not a
dictionary. You actually want to iterate over `itervalues()` instead. Update
your template code as follows:

    
    
    {% for l in result.itervalues() %}
    <div class="link">
        <a href="{{ l.url }}"> {{l.title}}</a>
        <img src="{{ l.img }}" width="100" height="100">
    </div>
    {% endfor %}
    

I believe that should get you the behaviour you want.

* * *

Note that this will return the values in a random order (as iterating over a
dictionary is random). If you wanted to sort by the key, you could modify the
template as follows:

    
    
    {% for key in result.iterkeys()|sort %}
    <div class="link">
        {%- set val=result[key] %}
        <a href="{{ val.url }}"> {{val.title}}</a>
        <img src="{{ val.img }}" width="100" height="100">
    </div>
    {% endfor %}
    

Here we iterate over the sorted keys, get the associated value, and then drop
it into the template.

You could also swap out the `sort` filter for another filter which applies the
ordering of your choice.

* * *

Here’s a minimal example that demonstrates the new template:

    
    
    TEMPLATE_STR = """
    {% for l in result.itervalues() %}
    <div class="link">
        <a href="{{ l.url }}"> {{l.title}}</a>
        <img src="{{ l.img }}" width="100" height="100">
    </div>
    {% endfor %}
    """
    
    from jinja2 import Template
    
    template = Template(TEMPLATE_STR)
    
    class democlass(object):
        def getTitle(self): return "Hello world"
        def getLink(self): return "google.co.uk"
        def getImg(self): return "myimage.png"
    
    class democlass2(object):
        def getTitle(self): return "Foo bar"
        def getLink(self): return "stackoverflow.com"
        def getImg(self): return "a_photo.jpeg"
    
    l = democlass()
    m = democlass2()
    
    dict1 = {}
    dict1['l'] =  { 'title': l.getTitle(), 'url': l.getLink(), 'img': l.getImg() }
    dict1['m'] =  { 'title': m.getTitle(), 'url': m.getLink(), 'img': m.getImg() }
    
    print template.render(result=dict1)
    

Here's the HTML it returns:

    
    
    <div class="link">
        <a href="stackoverflow.com"> Foo bar</a>
        <img src="a_photo.jpeg" width="100" height="100">
    </div>
    
    <div class="link">
        <a href="google.co.uk"> Hello world</a>
        <img src="myimage.png" width="100" height="100">
    </div>
    

