Django请求触发KeyError: 'main',OpenWeatherMap API调用问题求助
Hey there, let’s tackle that frustrating KeyError: 'main' you’re running into while building your weather app with Django and requests. I’ve dealt with my fair share of API response quirks, so let’s break this down step by step.
Why This Happens
That error means you’re trying to access the 'main' key in the API response dictionary… but it doesn’t exist. This almost always boils down to one of these scenarios:
- Your API request failed (invalid key, wrong city name, missing parameters) and returned an error response instead of weather data.
- You’re skipping a check for a successful request and diving straight into nested data.
- You’re hitting the wrong OpenWeatherMap endpoint (e.g., using the forecast endpoint instead of current weather), which has a different response structure.
Step 1: See What the API Actually Returns
First things first—let’s look at the full response the API is sending back. Add a print statement (or use Django’s logger) right after you parse the JSON to see exactly what you’re working with. Here’s how to adjust your view:
import requests from django.shortcuts import render from urllib.parse import quote # For handling non-English city names def get_weather(request): if request.method == 'POST': city = request.POST.get('city', '') api_key = 'your_openweathermap_key' # Encode city names with spaces/non-English characters encoded_city = quote(city) url = f"https://api.openweathermap.org/data/2.5/weather?q={encoded_city}&appid={api_key}" response = requests.get(url) data = response.json() # Print the full response to debug (remove in production) print("Full API Response:", data) # Now handle the response properly context = {} # Check if the request was successful (OpenWeatherMap uses cod: 200 for success) if data.get('cod') == 200: # Safely access nested data main_data = data.get('main', {}) temp_celsius = main_data.get('temp', 0) - 273.15 # Convert Kelvin to Celsius context = { 'city': city, 'temperature': round(temp_celsius, 2), 'humidity': main_data.get('humidity') } else: # Handle errors (city not found, invalid key, etc.) error_msg = data.get('message', 'Something went wrong with the weather request') context['error'] = error_msg return render(request, 'weather/result.html', context) return render(request, 'weather/form.html')
Common Fixes to Implement
- Validate API Success First: Always check the
codfield in the response. OpenWeatherMap returns200for successful requests, and other codes (like404for missing cities,401for invalid keys) when something’s wrong. - Use
.get()for Safe Dictionary Access: Instead ofdata['main']['temp'], usedata.get('main', {}).get('temp'). This returnsNone(or a default value you specify) if the key doesn’t exist, avoiding the KeyError. - Encode Non-English City Names: If users are searching for cities with spaces or non-Latin characters (like "New York" or "北京"), use
urllib.parse.quote()to properly encode the city name in the URL. - Double-Check Your API Endpoint: Make sure you’re using the current weather endpoint (
/data/2.5/weather). If you accidentally use the forecast endpoint (/data/2.5/forecast), the response structure won’t have a top-level'main'key.
Example Error Responses to Watch For
If your request fails, the API will send back something like this instead of weather data:
- Invalid API key:
{"cod":401, "message": "Invalid API key."} - City not found:
{"cod":"404", "message": "city not found"}
These responses don’t have a 'main' key, so trying to access it directly will throw that KeyError.
By adding these checks and debugging steps, you’ll not only fix the current error but also make your app more resilient to unexpected API behavior.
内容的提问来源于stack exchange,提问作者user10822828

