Django, looping through openweather icons always displays the last icon instead of appended city icon

Question:

I am trying to build out a weather app using openweather api and what I want to do is replace the icon png’s with my own customized icon set.

In order to do this, I have referenced the openweather api png codes as seen here: https://openweathermap.org/weather-conditions. I have written some code that states if this code equals ’01d’ then replace the icon code with my custom data image src.

The issue is when looping through (after I have added a city), I am always appending the last image which in this case is the data code for ’50n’ rather than the correct weather code for that city.

here is the code in my 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)

What am I doing wrong or am I missing something?

Asked By: Who Me Dunno Mate

||

Answers:

        icon = weather['icon']

This sets a variable icon to reference the string inside the dictionary.

            icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/01d.svg'

This reassigns that variable to a URL string. It does NOT change the dictionary like you might think.

    context = {'weather_data' : weather_data, 'icon': icon}

After the loop, you set a single value in the context which will be the last icon url.

Two suggestions:

  1. Don’t reassign a variable to mean something else. Use two different variables instead. So instead of

            icon = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/01d.svg'
    

    do

            icon_url = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/01d.svg'
    
  2. Better yet, store the url in each dictionary:

            weather['icon_url'] = 'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/01d.svg'
    

    Now you will have a url for the icon in each city.

  3. You can build the URL directly from the name of the icon without all the if statements. Do this just once instead of 50 times:

            weather['icon_url'] = f'https://dar-group-150-holborn.s3.eu-west-2.amazonaws.com/images/{icon}.svg'
    

    Alternatively, you can do this directly in the template. Since you didn’t share your template, I can’t give any details beyond this vague hint.

Answered By: Code-Apprentice
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.