Alice1
Alice1

Reputation: 33

How to get a Python dict into an HTML template using Flask/Jinja2

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.

Upvotes: 3

Views: 8782

Answers (2)

Mounesh
Mounesh

Reputation: 744

# Python Code

from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def index():
    k = {
            "Movie" : "KGF Chapter 1",
            "Director" : "Prashant Neel",
            "Antagonist" : "Adheera"
        }

    return render_template("index.html", k=k)

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

<!-- Below is the HTML Code : --> 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>


<body>

    <h1> Your dictionary is here : {{k}} </h1>
    

</body>

</html>

Upvotes: 0

alexwlchan
alexwlchan

Reputation: 6098

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>

Upvotes: 3

Related Questions