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

Django天气应用:为API渲染的城市添加可用删除按钮

解决思路:将数据库City对象与API天气数据绑定

核心问题是你传给模板的只有纯API数据,没有关联对应的数据库City实例的id。解决办法是在视图中把每个City对象和它对应的天气数据打包,一起传给模板,这样循环时既能拿到天气信息,又能拿到City的id。

1. 修改视图,关联City对象与天气数据

把原来的纯API数据列表改成包含City对象和对应天气信息的字典:

# views.py
import requests
from django.shortcuts import render, redirect
from .models import City

def weather(request):
    if request.method == 'POST':
        city_name = request.POST.get('city').strip()
        if city_name and not City.objects.filter(name__iexact=city_name).exists():
            City.objects.create(name=city_name)
        return redirect('weather')
    
    cities = City.objects.all()
    weather_entries = []  # 替换原weather_data列表
    api_key = '你的API密钥'
    base_url = 'http://api.openweathermap.org/data/2.5/weather'
    
    for city in cities:
        params = {
            'q': city.name,
            'appid': api_key,
            'units': 'metric'
        }
        response = requests.get(base_url, params=params)
        if response.status_code == 200:
            data = response.json()
            weather_entries.append({
                'city_obj': city,  # 传入数据库的City实例
                'temp': data['main']['temp'],
                'desc': data['weather'][0]['description'],
                'icon': data['weather'][0]['icon']
            })
        # 可添加API请求失败的处理逻辑,比如跳过该城市
    
    context = {'weather_entries': weather_entries}
    return render(request, 'weather.html', context)

def delete_city(request, city_id):
    City.objects.filter(id=city_id).delete()  # 用filter避免DoesNotExist异常
    return redirect('weather')

2. 修改模板,使用City对象的id生成删除链接

现在循环weather_entries,每个条目里的city_obj就是数据库中的City实例,直接调用它的id即可:

<!-- weather.html -->
<form method="POST">
    {% csrf_token %}
    <input type="text" name="city" placeholder="输入城市名称" required>
    <button type="submit">添加城市</button>
</form>

{% for entry in weather_entries %}
    <div class="city-card">
        <h3>{{ entry.city_obj.name }}</h3>
        <p>当前温度: {{ entry.temp }}°C</p>
        <p>天气状况: {{ entry.desc }}</p>
        <img src="http://openweathermap.org/img/w/{{ entry.icon }}.png" alt="{{ entry.desc }}">
        <!-- 用entry.city_obj.id获取数据库中的id -->
        <form method="POST" action="{% url 'delete_city' entry.city_obj.id %}" style="display: inline;">
            {% csrf_token %}
            <button type="submit" onclick="return confirm('确定要删除这个城市吗?')">删除</button>
        </form>
    </div>
{% empty %}
    <p>还没有添加任何城市,输入城市名称开始吧!</p>
{% endfor %}

注意:把删除链接改成POST表单更安全,避免GET请求误删数据,同时添加确认提示降低误操作概率。

3. 验证URL配置

确保你的urls.py中删除路由配置正确:

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.weather, name='weather'),
    path('delete/<int:city_id>/', views.delete_city, name='delete_city'),
]

问题根源说明

  • 原来的视图只传给模板API返回的纯数据(字符串、数字),没有携带数据库City模型的id,模板无法生成delete_city路由需要的city_id参数,因此抛出NoReverseMatch错误。
  • 拆分视图单独查询数据库时,虽然能拿到City的id,但无法将API数据与这些City对象关联后传给模板,导致无法同时渲染天气信息。

现在的方法通过将City对象和对应天气数据打包,一次性传给模板,既解决了删除按钮的id问题,又能正常渲染天气信息。

内容的提问来源于stack exchange,提问作者blueberry.py

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 13:01:07