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

Django开发天气应用避免KeyError的更优实现方式

Django天气应用输入容错优化方案

现有代码可优化点

  • 冗余的while循环:判断输入是否为空、城市是否匹配的逻辑仅需单次判断,不需要while循环加break的写法
  • 城市校验逻辑存在bug:将城市匹配结果转成字符串做包含判断,会出现子串误匹配问题
  • 变量未初始化:GET请求访问首页时city变量未定义,会直接抛出NameError
  • 未覆盖接口异常场景:仅做本地城市校验无法覆盖第三方接口返回错误、超时、无权限等情况,直接取返回值的键仍会触发KeyError
  • 重复开销:每次POST请求都重新实例化GeonamesCache,没有必要

优化后代码

from django.shortcuts import render
import requests
from datetime import datetime
import geonamescache

# 全局初始化资源,避免每次请求重复加载
gc = geonamescache.GeonamesCache()
DEFAULT_CITY = "Amsterdam"
WEATHER_API = 'https://api.openweathermap.org/data/2.5/weather'
API_KEY = 'MY_KEY'

def home(request):
    city = DEFAULT_CITY
    error_msg = None

    # 处理POST查询请求
    if request.method == "POST":
        # 安全取POST参数,自动去除首尾空白字符
        input_city = request.POST.get('search-city', '').strip()
        if not input_city:
            error_msg = "输入不能为空,已展示默认城市天气"
        else:
            # 直接判断匹配列表是否为空,避免字符串匹配的误判问题
            match_result = gc.get_cities_by_name(input_city.title())
            if match_result:
                city = input_city
            else:
                error_msg = "未匹配到对应城市,已展示默认城市天气"

    # 初始化返回给模板的默认数据
    weather_data = {
        'description': '暂无数据',
        'temp': '暂无数据',
        'icon': '',
        'day': datetime.now().strftime("%d/%m/%Y %H:%M"),
        'country': '',
        'city': city,
        'error_msg': error_msg
    }

    # 接口请求全链路加异常捕获
    try:
        req_params = {
            'q': city,
            'appid': API_KEY,
            'units': 'metric'
        }
        # 加超时避免请求卡死
        resp = requests.get(url=WEATHER_API, params=req_params, timeout=10)
        # 状态码非200直接抛异常
        resp.raise_for_status()
        res = resp.json()

        # 用get方法安全取值,不存在则用默认值,彻底避免KeyError
        weather_data['city'] = res.get('name', city)
        weather_info = res.get('weather', [{}])[0]
        weather_data['description'] = weather_info.get('description', '暂无天气描述')
        weather_data['icon'] = weather_info.get('icon', '')
        main_data = res.get('main', {})
        weather_data['temp'] = main_data.get('temp', '暂无温度数据')
        sys_data = res.get('sys', {})
        weather_data['country'] = sys_data.get('country', '')
    except Exception as e:
        weather_data['error_msg'] = f"天气查询失败:{str(e)}"

    return render(request, 'weatherapp/home.html', weather_data)

核心优化逻辑

  • 移除所有无意义的while循环,用线性分支判断完成输入校验,逻辑可读性更高
  • 全局初始化城市缓存、常量配置,减少重复实例化的性能开销
  • 用request.POST.get()安全取参,配合strip()过滤全空格的无效输入
  • 城市校验直接判断匹配列表是否非空,替代原有的字符串包含判断,避免子串误判
  • 提前初始化默认城市变量,兼容GET请求访问场景,不会出现变量未定义的错误
  • 接口请求增加超时、状态码校验,全链路捕获异常
  • 解析接口返回值时统一用.get()方法取值,为每个字段设置兜底默认值,从根源避免KeyError
  • 增加错误提示字段,前端可以直接展示提示信息,用户体验更好

内容的提问来源于stack exchange,提问作者manos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 13:30:55