Django集成OpenWeather API时循环显示图标异常问题排查
问题描述
我正在开发基于OpenWeather API的天气应用,想要用自定义图标集替换API默认的PNG图标。已参照OpenWeather天气编码规则编写匹配逻辑,当编码为'01d'等时替换为自定义图标地址,但循环遍历添加的城市时,总是显示最后一个图标(如'50n'对应的图标),而非对应城市的正确图标。以下是views.py中的代码:
def weather(request): url = 'http://api.openweathermap.org/data/2.5/weather?q={}&units=metric&appid=<MYAPPKEY>' cities = City.objects.all() weather_data = [] for city in cities: city_weather = requests.get(url.format(city)).json() weather = { 'city' : city, 'temperature' : city_weather['main']['temp'], 'description' : city_weather['weather'][0]['description'], 'icon' : city_weather['weather'][0]['icon'], } icon = weather['icon'] if icon == '01d': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/01d.svg' elif icon == '01n': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/01n.svg' elif icon == '02d': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/02d.svg' elif icon == '02n': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/02n.svg' elif icon == '03d': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/03d.svg' elif icon == '03n': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/03n.svg' elif icon == '04d': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/04d.svg' elif icon == '04n': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/04n.svg' elif icon == '09d': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/09d.svg' elif icon == '09n': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/09n.svg' elif icon == '10d': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/10d.svg' elif icon == '10n': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/10n.svg' elif icon == '11d': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/11d.svg' elif icon == '11n': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/11n.svg' elif icon == '13d': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/13d.svg' elif icon == '13n': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/13n.svg' elif icon == '50d': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/50d.svg' elif icon == '50n': icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/50n.svg' weather_data.append(weather) context = {'weather_data' : weather_data, 'icon': icon} return render(request, 'weather/weather.html', context)
问题分析与解决方案
核心错误
- 未更新对应城市的图标字段:你仅将
weather['icon']赋值给变量icon并修改,但从未把替换后的图标地址存回weather字典,导致weather_data里的城市对象仍保留API返回的原始编码。 - 上下文传递错误:
context中单独传递的icon变量,在循环结束后只会保留最后一次循环的结果,模板若误用这个全局变量,就会出现所有城市显示同一图标的问题。
修正步骤
步骤1:更新weather字典的icon字段
在修改完icon变量后,将其赋值回weather字典:
# 替换完图标地址后添加此行 weather['icon'] = icon
步骤2:移除全局icon变量
每个城市的图标已包含在weather_data的元素中,无需单独传递全局icon,修改上下文:
context = {'weather_data': weather_data}
代码优化建议
用字典映射替代冗余的if-elif判断,提升代码可读性和维护性:
def weather(request): url = 'http://api.openweathermap.org/data/2.5/weather?q={}&units=metric&appid=<MYAPPKEY>' cities = City.objects.all() # 定义图标映射字典 icon_mapping = { '01d': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/01d.svg', '01n': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/01n.svg', '02d': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/02d.svg', '02n': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/02n.svg', '03d': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/03d.svg', '03n': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/03n.svg', '04d': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/04d.svg', '04n': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/04n.svg', '09d': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/09d.svg', '09n': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/09n.svg', '10d': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/10d.svg', '10n': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/10n.svg', '11d': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/11d.svg', '11n': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/11n.svg', '13d': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/13d.svg', '13n': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/13n.svg', '50d': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/50d.svg', '50n': 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/50n.svg' } weather_data = [] for city in cities: city_weather = requests.get(url.format(city)).json() original_icon = city_weather['weather'][0]['icon'] # 若找不到对应映射,保留原始编码(可选) custom_icon = icon_mapping.get(original_icon, original_icon) weather = { 'city': city, 'temperature': city_weather['main']['temp'], 'description': city_weather['weather'][0]['description'], 'icon': custom_icon } weather_data.append(weather) context = {'weather_data': weather_data} return render(request, 'weather/weather.html', context)
模板使用示例
确保模板遍历weather_data,取出每个城市的专属图标:
{% for item in weather_data %} <div class="city-card"> <h3>{{ item.city }}</h3> <p>{{ item.temperature }}°C</p> <p>{{ item.description }}</p> <img src="{{ item.icon }}" alt="weather icon"> </div> {% endfor %}
内容的提问来源于stack exchange,提问作者Who Me Dunno Mate
相关产品推荐
相关产品推荐

