Django遍历模型生成各城市天气信息仅返回首条数据问题排查
问题描述
遍历Django模型为每个城市生成对应天气信息时,接口仅返回第一个城市的天气数据,未返回所有城市的对应结果。
原有代码
models.py
from django.db import models from pytz import timezone # Create your models here. class city(models.Model): name=models.CharField(max_length=40) def __str__(self): return self.name class weather(models.Model): City=models.ForeignKey(city, null=True, on_delete=models.CASCADE) country=models.CharField(max_length=40) timezone=models.CharField(max_length=40) temperature=models.FloatField() humidity=models.FloatField() status=models.CharField(max_length=40) def __str__(self): return self.country
serializers.py
from rest_framework import serializers from .models import weather,city class CitySerializers(serializers.ModelSerializer): class Meta: model=city fields='__all__' class WeatherSerializers(serializers.ModelSerializer): class Meta: model=weather fields='__all__'
views.py
from django.shortcuts import render import requests from .models import weather,city from .serializers import WeatherSerializers from rest_framework.decorators import api_view from rest_framework.response import Response from geopy.geocoders import Nominatim # Create your views here. @api_view(['GET']) def weatherinfo(request): Cit=city.objects.all() geolocator=Nominatim(user_agent="XXXXXXXX") key= 'XXXXXXXXXXX' for obj in Cit: #cit=city.objects.get(city,id=obj) location=geolocator.geocode(obj) coordinates=(location.latitude,location.longitude) lat=coordinates[0] long=coordinates[1] url='https://api.openweathermap.org/data/2.5/weather?lat={}&lon={}&appid={}'.format(lat,long,key) city_weather=requests.get(url).json() weather_data=weather.objects.create( City=obj, country=city_weather['sys']['country'], timezone=city_weather['timezone'], temperature=city_weather["main"]["temp_max"], humidity=city_weather["main"]["humidity"], status=city_weather["weather"][0]["description"], ) serializer=WeatherSerializers(weather_data, many=False) return Response(serializer.data)
问题原因
return Response(serializer.data)写在了for循环内部:
- 循环处理完第一个城市后就直接触发返回,视图函数立刻终止运行
- 剩余城市的遍历、天气接口请求、数据入库逻辑完全不会执行,因此只会返回第一个城市的天气数据
修复方案
调整代码结构:
- 将返回逻辑移到循环外部
- 循环内仅完成所有城市的天气拉取、数据存储,把生成的天气对象统一存入列表
- 所有城市处理完成后,对整个天气列表做序列化,一次性返回结果
修复后的views.py代码:
from django.shortcuts import render import requests from .models import weather,city from .serializers import WeatherSerializers from rest_framework.decorators import api_view from rest_framework.response import Response from geopy.geocoders import Nominatim # Create your views here. @api_view(['GET']) def weatherinfo(request): city_list = city.objects.all() geolocator = Nominatim(user_agent="XXXXXXXX") key = 'XXXXXXXXXXX' weather_result = [] for obj in city_list: # 显式传入name字段做地理编码,避免依赖__str__方法带来的不确定性 location = geolocator.geocode(obj.name) lat, long = location.latitude, location.longitude url = 'https://api.openweathermap.org/data/2.5/weather?lat={}&lon={}&appid={}'.format(lat, long, key) city_weather = requests.get(url).json() weather_data = weather.objects.create( City=obj, country=city_weather['sys']['country'], timezone=city_weather['timezone'], temperature=city_weather["main"]["temp_max"], humidity=city_weather["main"]["humidity"], status=city_weather["weather"][0]["description"], ) weather_result.append(weather_data) # 序列化列表时需要设置many=True serializer = WeatherSerializers(weather_result, many=True) return Response(serializer.data)
补充说明:当前逻辑每次调用接口都会为每个城市新增一条天气记录,如果需要更新已有城市的最新天气而非重复生成冗余数据,可以将
weather.objects.create替换为weather.objects.update_or_create,以关联的City字段为查询条件更新对应字段即可。
内容的提问来源于stack exchange,提问作者Christopher Ifeoluwa Oni
相关产品推荐
相关产品推荐

