Django项目中NewsAPI无法获取指定城市新闻求助
Django接入NewsAPI获取城市新闻失败的解决方案
核心问题分析
- 视图分离导致数据断层:表单默认提交到
index视图,news视图从未被触发,模板中的articles变量始终为空 - 初始值类型错误:
news视图中articles默认值为字典{},但模板需要遍历列表,会引发遍历异常 - 异常处理过于笼统:全局
except捕获所有错误,无法定位具体问题(如API密钥无效、请求超时、返回数据结构异常) - NewsAPI参数优化不足:仅用城市名搜索易返回无关结果,结合国家代码能大幅提升匹配准确性
修复步骤
1. 合并视图逻辑,统一获取天气与新闻数据
修改views.py,将两类数据的请求逻辑合并到index视图,确保一次提交能同时获取天气和新闻:
from django.shortcuts import render import requests from datetime import datetime from requests.exceptions import RequestException def index(request): city_weather_update = {} articles = [] # 初始化为空列表,避免遍历错误 if request.method == 'POST': try: # 配置API密钥(建议移至settings.py,通过环境变量读取) WEATHER_API_KEY = '你的OpenWeatherAPI密钥' NEWS_API_KEY = '你的NewsAPI密钥' city_name = request.POST.get('city').strip() # 获取天气数据 weather_url = f'https://api.openweathermap.org/data/2.5/weather?q={city_name}&appid={WEATHER_API_KEY}&units=metric' weather_response = requests.get(weather_url) weather_response.raise_for_status() # 触发HTTP错误异常 weather_data = weather_response.json() # 格式化时间 current_time = datetime.now() formatted_time = current_time.strftime("%A, %B %d %Y, %H:%M:%S %p") city_weather_update = { 'city': city_name, 'description': weather_data['weather'][0]['description'], 'icon': weather_data['weather'][0]['icon'], 'temperature': f'Temperature: {weather_data["main"]["temp"]} °C', 'country_code': weather_data['sys']['country'], 'wind': f'Wind: {weather_data["wind"]["speed"]} km/h', 'humidity': f'Humidity: {weather_data["main"]["humidity"]}%', 'time': formatted_time } # 结合国家代码获取精准新闻 country_code = weather_data['sys']['country'].lower() news_url = f'https://newsapi.org/v2/top-headlines?q={city_name}&country={country_code}&apiKey={NEWS_API_KEY}' news_response = requests.get(news_url) news_response.raise_for_status() news_data = news_response.json() articles = news_data.get('articles', []) # 用get避免KeyError except RequestException as e: # 调试用:打印错误信息,生产环境可写入日志 print(f"API请求错误: {str(e)}") return render(request, 'error.html', {'error': str(e)}) except KeyError as e: print(f"数据解析错误: 缺少字段 {str(e)}") return render(request, 'error.html', {'error': f'数据解析错误,缺少必要字段: {str(e)}'}) context = {'city_weather_update': city_weather_update, 'articles': articles} return render(request, 'index.html', context) # 移除原有的news视图,不再需要
2. 优化模板,适配数据变化
修改index.html,优化空数据提示逻辑,同时处理首次加载无数据的场景:
{% extends 'base.html' %} {% block content %} <div class="row justify-content-center my-5"> <div class="col-md-5"> <div class="mt-4 p-5 bg-success text-white rounded mb-3"> <h1>Weather Update App</h1> </div> <form action="" method="POST"> {% csrf_token %} <div class="input-group"> <input type="text" required class="form-control" name="city" placeholder="Search City......."> <div class="input-group-append"> <button class="btn btn-success" type="submit"> Search </button> </div> </div> </form> <hr> <!-- 仅当有天气数据时展示天气卡片 --> {% if city_weather_update %} <div class="card"> <div class="card-body"> <img src="http://openweathermap.org/img/w/{{ city_weather_update.icon }}.png" alt="Weather Icon"> <div class="card-text float-end">{{ city_weather_update.time }}</div> <div class="card-text"><h5>{{ city_weather_update.city }} {{ city_weather_update.country_code }}</h5></div> <div class="card-text"><h6>{{ city_weather_update.temperature }}</h6></div> <div class="card-text"><h6>{{ city_weather_update.description | title }}</h6></div> <div class="card-text"><h6>{{ city_weather_update.wind }}</h6></div> <div class="card-text"><h6>{{ city_weather_update.humidity }}</h6></div> </div> </div> {% endif %} <!-- 新闻展示区域 --> {% if city_weather_update %} {% if articles %} <h2 class="mt-4">News Articles:</h2> {% for article in articles %} <div class="card my-3"> <div class="card-body"> <h5 class="card-title">{{ article.title }}</h5> {% if article.description %} <p class="card-text">{{ article.description }}</p> {% endif %} <a href="{{ article.url }}" class="btn btn-primary" target="_blank">Read More</a> </div> </div> {% endfor %} {% else %} <p class="mt-4">No news articles found for {{ city_weather_update.city }}.</p> {% endif %} {% else %} <p>Enter a city name to get weather and news updates.</p> {% endif %} </div> </div> {% endblock %}
额外注意事项
- NewsAPI免费版限制:免费版仅支持英文新闻,且有调用次数上限,如需多语言新闻需升级付费版
- 密钥安全:不要硬编码API密钥,建议在
settings.py中通过环境变量读取,如NEWS_API_KEY = os.getenv('NEWS_API_KEY') - 调试技巧:可在视图中打印
news_response.text,查看API返回的原始错误信息(如密钥无效、请求超限等)
内容的提问来源于stack exchange,提问作者Ash-Ketchum
相关产品推荐
相关产品推荐

