Получение ошибки при печати значений словаря в html

Я хочу вывести на печать подробную информацию о погоде в разных городах и написал код, как показано ниже. При извлечении данных я не могу получить данные в HTML.

views.py

from django.shortcuts import render

# Create your views here.
import urllib.request
import json
import requests

def display(request):
    city=['vijayawada','guntur','tenali','rajahmundry','amaravathi']
    for i in city:
        source = urllib.request.urlopen(
            'https://api.openweathermap.org/data/2.5/weather?q=' + i + '&units=metric&appid=5980455dc827c861d5ac4125c3673b43').read()
        list_of_data = json.loads(source)

        data = {
            "country_code": str(list_of_data['sys']['country']),
            "coordinate": str(list_of_data['coord']['lon']) + ', '
                          + str(list_of_data['coord']['lat']),

            "temp": str(list_of_data['main']['temp']) + ' °C',
            "pressure": str(list_of_data['main']['pressure']),
            "humidity": str(list_of_data['main']['humidity']),
            'main': str(list_of_data['weather'][0]['main']),
            'description': str(list_of_data['weather'][0]['description']),
            'icon': list_of_data['weather'][0]['icon'],
        }
        print(data)
    return render(request, "display.html",data)

display.html

<html>
<head>
    <title>API Display</title>
</head>
<body>
    <h1>Weather details</h1>
    <form>
{% for i in data %}
{{ country_code }}
{{ temp }}
{{ i }}
{% endfor %}
</form>
</body>
</html>

Я пытаюсь вывести значения словаря в html, но они не выводятся. В консоли значения печатаются правильно, что означает, что цикл for в views.py работает правильно. Пожалуйста, подскажите, где я ошибаюсь

Вы можете сделать функцию, которая обрабатывает запрос для каждого города:

def get_city_weather(city_name):
    source = urllib.request.urlopen(
            'https://api.openweathermap.org/data/2.5/weather?q=' + city_name + '&units=metric&appid=5980455dc827c861d5ac4125c3673b43').read()
    list_of_data = json.loads(source)

    return {
        "country_code": str(list_of_data['sys']['country']),
        "coordinate": str(list_of_data['coord']['lon']) + ', '
                      + str(list_of_data['coord']['lat']),

        "temp": str(list_of_data['main']['temp']) + ' °C',
        "pressure": str(list_of_data['main']['pressure']),
        "humidity": str(list_of_data['main']['humidity']),
        'main': str(list_of_data['weather'][0]['main']),
        'description': str(list_of_data['weather'][0]['description']),
        'icon': list_of_data['weather'][0]['icon'],
    }

Затем используйте dict comprehension для составления диктанта data для отправки в шаблон:

def display(request):
    cities=['vijayawada','guntur','tenali','rajahmundry','amaravathi']
    
    data = {city_name: get_city_weather(city_name) for city_name in cities}

    return render(request, "display.html", data)

На данный момент data представляет собой словарь, ключом которого является название города, а значением - словарь, возвращаемый get_city_weather, поэтому он выглядит следующим образом (сокращенно):

{'vijayawada': 
    {'country_code': 'ABC'
    # ...
    }
# ...
}

Затем в шаблоне вы можете выполнить цикл, например, так:

{% for city_name, city_weather in data.items %}
The temperature in {{city_name}} is {{city_weather.temp}}
 and the air pressure is {{city_weather.pressure}}.
{% endfor %}

Или, если вы не хотите указывать ключи типа temp и pressure, вы можете сделать так:

{% for city_name, city_weather in data.items %}
<p>Weather data for {{city_name}}:</p>

<ul>
{% for k,v in city_weather.items %}
  <li>{{k}}: {{v}}</li>
{% endfor %}
</ul>

<hr />
{% endfor %}

АФАИК, система шаблонов джанго распознает переменную dict точно так же, как это делает сам Python.
Таким образом, если мы попытаемся преобразовать код вашего шаблона обратно в код Python, мы получим что-то вроде этого:

for i in data:
  print(country_code)
  print(temp)
  print(i)

Теперь спросите себя: будет ли это работать?
. Очевидно, что нет.

Итак, как именно в Python можно выполнить цикл и получить доступ к значениям dict?
Вы можете сделать это следующим образом:

for i in data:
  print(i)

Или с переменными цикла k,v (лучший способ):

for k, v in enumerate(data):
  print(f"key: {k}, value: {v}")

Но в коде вашего шаблона вы пытаетесь получить доступ к определенным значениям с ключом (country_code и т.д.).
В этом случае, вероятно, вам даже не нужно использовать цикл for.
И ваш файл display.html может быть переписан следующим образом:

<html>
<head>
    <title>API Display</title>
</head>
<body>
    <h1>Weather details</h1>
    <form>
{{ data.country_code }}
{{ data.temp }}
</form>
</body>
</html>

Кроме того, как я вижу, ваше представление извлекает это data для каждого заданного города.
А вы передаете в шаблон только последнее.
Чтобы исправить это, вы должны переписать код представления.

Я думаю, что можно добавить новую переменную collected_data и затем в конце каждого цикла получения данных просто добавлять data к этой новой переменной.
После этого, вы можете просто передать collected_data в шаблон.
И затем перебирать их в шаблоне.

Но я точно не знаю, как должен выглядеть ваш шаблон, поэтому оставляю это на ваше усмотрение.
Я попытался объяснить, в чем проблема.

Это потому, что вы перезаписываете свой словарь данных. Он передается только как один объект, он должен что-то отобразить, если вы попробуете {{data}} или {{data.country_code}}, {{data.temp}}...

Один из способов решения этой проблемы - иметь вложенный словарь с данными каждого города:

views.py

def loop_dict(request):
    cities=['vijayawada','guntur','tenali','rajahmundry','amaravathi']
    data = {}
    for city in cities:
        source = urllib.request.urlopen(
            'https://api.openweathermap.org/data/2.5/weather?q=' + city + '&units=metric&appid=5980455dc827c861d5ac4125c3673b43').read()
        list_of_data = json.loads(source)

        data[city] = {
            "country_code": str(list_of_data['sys']['country']),
            "coordinates": {
                'latitude':  str(list_of_data['coord']['lat']),
                'longitude': str(list_of_data['coord']['lon'])
            },
            "temp": str(list_of_data['main']['temp']) + ' °C',
            "pressure": str(list_of_data['main']['pressure']),
            "humidity": str(list_of_data['main']['humidity']),
            'main': str(list_of_data['weather'][0]['main']),
            'description': str(list_of_data['weather'][0]['description']),
            'icon': list_of_data['weather'][0]['icon'],
        }
    context = {'data': data}

    return render(request, 'loop_dict.html', context)

loop_dict.html:

{% extends 'base.html' %}

{% block content %}
    {% for key, obj in data.items %}
        <h2>City: {{key}}</h2><br>
        <p>Country Code: {{obj.country_code}}</p><br>
        <p>Latitude: {{obj.coordinates.latitude}}</p><br>
        <p>Longitude: {{obj.coordinates.longitude}}</p><br>
        <p>Temp: {{obj.temp}}</p><br>
        <hr>
    {% endfor %}
{% endblock %}
Вернуться на верх