1

I have a dictionary which has all the country codes and the corresponding country names, a sample of it looks like this:

{'AF': 'Afghanistan'}
{'AL': 'Albania'}
{'DZ': 'Algeria'}
{'AD': 'Andorra'}
{'AO': 'Angola'}

When i followed this stack overflow question: How to iterate through a list of dictionaries in Jinja template? to try and iterate through the countries I had an issue as it's not adding any elements. This is my code:

{% extends "base.html" %} {% block title %}Test{% endblock %}
{% block content %}
<div class="container pt-5">
      <h1 align="center">TEST PAGE</h1>
</div>
{% for dict_item in countries %}
    {% for key,value in dict_item.items %}
        <h1>Key: {{ key }}</h1>
        <h2>Value: {{ value }}</h2>
    {% endfor %}
{% endfor %}
{% endblock %}

It's not adding any headings and when i tried dict_items.items() (with brackets after items), I got an error of: jinja2.exceptions.UndefinedError: 'str object' has no attribute 'items'

I'm not too sure what's going wrong. Any help would be much appreciated.

(Just incase it's useful, this is my views.py:)


@views.route("/test", methods=["GET"])
@login_required
def test():
    countries = Country.query.all()
    for country in countries:
        countriess = {}
        countriess[country.country_code] = country.country_name
        print(countriess)

    return render_template("TEST.html", user=current_user, countries=countriess)
Tester321
  • 103
  • 2
  • 8

2 Answers2

3

Try changing views.py to:

@views.route("/test", methods=["GET"])
@login_required
def test():
    countries = Country.query.all()
    countriess = []
    for country in countries:
        countriess.append({country.country_code: country.country_name})

    return render_template("TEST.html", user=current_user, countries=countriess)

This code will create a list of dictionaries countries, there is not need to change the templating code.

Dani Mesejo
  • 61,499
  • 6
  • 49
  • 76
  • Hello, this works great, is countriess a list or dictionary? – Tester321 Oct 21 '21 at 11:25
  • countriess is a list of dictionaries – Dani Mesejo Oct 21 '21 at 11:26
  • Ok that makes sense. I have a dropdown menu and I wanted to add all the countries to it. ``` {% for dict_item in countries %} {% for key,value in dict_item.items() %}
    {% endfor %} {% endfor %} ``` Could you please explain why this isn't adding anything. Might be easier to read here: https://pastebin.com/wxQmHuS7
    – Tester321 Oct 21 '21 at 11:28
  • Sorry but I cannot tell – Dani Mesejo Oct 21 '21 at 11:40
  • Oh sorry I thought I replied, I made a stupid mistake but your solution works perfectly. Thanks – Tester321 Nov 04 '21 at 21:39
1

in views.py, you set countries=countriess for template rendering. countriess is re-initialised in the for loop in the test function (countriess = {}), so the countriess passed along to the template is actually a {country_code: country_name} pair for the last country from the countries list.

Going back to the actual error though: when you iterate over countries dictionary within the template ({% for dict_item in countries %}), you actually iterate over keys of countries, which, as I said before, is countriess from the views.py, so basically you just retrieve the country_code of the last country from countries. So the dict_item is actually a string (country code), hence you get the error for {% for key,value in dict_item.items %}, thinking that it is actually a dictionary and not a string.

TL;DR I think that you meant to do countries=countries rather than countries=countriess in views.py. Then the rest of the code would make sense. (I assume the for loop with countriess was just for debugging?)

  • I tried your change and seem to have received an error: ``jinja2.exceptions.UndefinedError: 'website.models.Country object' has no attribute 'items'`` – Tester321 Oct 21 '21 at 11:24
  • Oh okay, it's all about the types. I thought `countries` might be a dictionary, but it is a separate Country class. In that case you indeed have to create a dictionary out of the values of `country` as you need (as suggested in the accepted answer). – Jakub Bober Oct 25 '21 at 19:20