Получение ошибки при печати значений словаря в 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 %}