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
相关产品推荐
相关产品推荐

