You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 15:39:59