0

I am attempting to loop through a list of dictionaries, using the values of the keys as HTML attributes within the jinja template. But the template doesn't render any of the data. I've verified the data is correct when I pass it in to the render_template function in the routes file.

I've gone through a number of StackOverflow questions, notably How to iterate through a list of dictionaries in jinja template? but to no avail.

Here's my data structure:

[
  {
    'name': 'chicken pie',
    'image': 'chicken.jpg',
    'url': 'chicken.html'
  },
  {
    'name': 'chicken sandwich',
    'image': 'sandwich.jpg',
    'url': 'sandwich.html'
  }
]

And my template is:

<div class="page-header">
  <h1>Recipes Matching {{ query }}</h1>
  {% for dict_item in names %}
    <div>
      <img src="{{ dict_item['image'] }}" height="100" width="100">
      <a href="{{ dict_item['url'] }}">{{ dict_item['name'] }}</a>
    </div>
  {% endfor %}
</div>
user22927
  • 13
  • 1
  • 4

1 Answers1

3

It is much easier to convert your structure to a list of class objects, with the dictionary keys as attributes:

class Item:
  def __init__(self, vals):
    self.__dict__ = vals

@app.route('/yourroute')
def your_route():   
  data = [{'name': 'chicken pie', 'image': 'chicken.jpg', 'url': 'chicken.html'}, {'name': 'chicken sandwich', 'image': 'sandwich.jpg', 'url': 'sandwich.html'}]
  return flask.render_template('your_template.html', names = [Item(i) for i in data])

Lastly, in your_template.html:

<div class="page-header">
<h1>Recipes Matching {{ query }}</h1>
{% for dict_item in names %}
  <div>
    <img src="{{dict_item.image}}" height="100" width="100">
    <a href="{{dict_item.url}}">{{dict_item.name}}</a>
  </div>
{% endfor %}
</div>
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
  • Thanks @Ajax1234 - that worked perfectly. One last question - I don't really understand why this works, so could you point me towards some further reading / a google search so that I can understand better? Thanks again! – user22927 May 11 '19 at 20:07
  • @user22927 Glad to help! The `__init__` method utilizes the builtin [`__dict__`](https://stackoverflow.com/questions/19907442/python-explain-dict-attribute) attribute to easily create attributes from the dictionary keys passed to it. `[Item(i) for i in data]` is a [list comprehension](https://stackoverflow.com/questions/20639180/explanation-of-how-nested-list-comprehension-works), and creates a new list with the `Item` objects. Please let me know if this helps you and that the links answer your larger questions. – Ajax1234 May 11 '19 at 20:11
  • An interesting approach. – Milovan Tomašević Sep 17 '21 at 19:46