如何通过Django读取JSON文件参数并实现天气应用功能?
Django天气应用问题解决方案
问题背景
开发Django天气应用,流程为:
- 用户输入城市名称
- 验证该城市是否存在于数据库中
- 若存在,将城市坐标传入天气API并返回天气数据
当前困惑:不清楚如何获取JSON文件的参数,不确定是否通过views实现、创建新模型或使用request方法,已耗时2小时未解决。
现有代码
views.py
from django.http import HttpResponse import requests from datetime import datetime from zoneinfo import ZoneInfo def weatherdata(request): response = requests.get('api is here').json() context = {'response':response} return render(request,'home.html',context) def citynamesinfo(request): response = request.FILES() #I don't what to do here # input localization # recognize specific coordenates
models.py
from django.db import models # Create your models here. class Weather(models.Model): city = models.CharField(max_length=100) temperature = models.DecimalField(max_digits=5,decimal_places=2) condition = models.CharField(max_length=100) precipitation = models.CharField(max_length=100, null=True) humidity = models.DecimalField(max_digits=5,decimal_places=2)
示例城市JSON结构
[{"geoname_id": "3112344", "name": "Ráfales", "ascii_name": "Rafales", "alternate_names": ["Rafales", "Rafels", "Ráfales", "Ráfels"], "feature_class": "P", "feature_code": "PPLA3", "country_code": "ES", "cou_name_en": "Spain", "country_code_2": null, "admin1_code": "52", "admin2_code": "TE", "admin3_code": "44194", "admin4_code": null, "population": 175, "elevation": null, "dem": 634, "timezone": "Europe/Madrid", "modification_date": "2012-03-04", "label_en": "Spain", "coordinates": {"lon": 0.01923, "lat": 40.8377}}]
解决方案
1. 新增City模型存储城市基础数据
要验证城市是否存在,直接操作数据库是最优方案,新增City模型来存储JSON中的城市信息:
from django.db import models class City(models.Model): geoname_id = models.CharField(max_length=20, unique=True) name = models.CharField(max_length=100) ascii_name = models.CharField(max_length=100) country_code = models.CharField(max_length=5) lon = models.FloatField() lat = models.FloatField() timezone = models.CharField(max_length=50) def __str__(self): return self.name class Weather(models.Model): # 关联City模型,替代原有的city字符字段 city = models.ForeignKey(City, on_delete=models.CASCADE) temperature = models.DecimalField(max_digits=5, decimal_places=2) condition = models.CharField(max_length=100) precipitation = models.CharField(max_length=100, null=True) humidity = models.DecimalField(max_digits=5, decimal_places=2) created_at = models.DateTimeField(auto_now_add=True)
2. 将JSON数据导入数据库
执行以下代码(可在Django Shell中运行,或编写自定义管理命令),把城市JSON数据批量导入到City模型:
import json from your_app_name.models import City # 替换为你的JSON文件路径 with open('path/to/cities.json', 'r', encoding='utf-8') as f: cities_data = json.load(f) for city in cities_data: # 用get_or_create避免重复导入 City.objects.get_or_create( geoname_id=city['geoname_id'], defaults={ 'name': city['name'], 'ascii_name': city['ascii_name'], 'country_code': city['country_code'], 'lon': city['coordinates']['lon'], 'lat': city['coordinates']['lat'], 'timezone': city['timezone'] } )
3. 编写处理用户输入的视图
替换原有视图,实现用户输入、城市验证、天气API调用的完整流程:
from django.shortcuts import render import requests from .models import City, Weather def home(request): if request.method == 'POST': # 获取用户输入的城市名称 city_name = request.POST.get('city_name') try: # 忽略大小写查询城市 city = City.objects.get(name__iexact=city_name) # 调用天气API,替换为你的API地址和所需参数 weather_api_url = f"your_weather_api_endpoint?lat={city.lat}&lon={city.lon}" weather_response = requests.get(weather_api_url).json() # 根据天气API返回结构提取数据,以下为示例 temperature = weather_response['main']['temp'] condition = weather_response['weather'][0]['main'] humidity = weather_response['main']['humidity'] # 处理降水数据,部分API可能无此字段 precipitation = weather_response.get('rain', {}).get('1h', '0mm') # 可选:将天气数据保存到数据库 Weather.objects.create( city=city, temperature=temperature, condition=condition, humidity=humidity, precipitation=precipitation ) # 传递数据到模板 context = { 'city': city.name, 'temperature': temperature, 'condition': condition, 'humidity': humidity, 'precipitation': precipitation } return render(request, 'weather_result.html', context) except City.DoesNotExist: # 城市不存在时返回提示 return render(request, 'home.html', {'error': '该城市不存在,请重新输入'}) # GET请求时显示输入表单 return render(request, 'home.html')
关键说明
- 无需使用
request.FILES:你要处理的是用户输入的城市名,不是上传文件,用request.POST获取即可。 - 必须导入
render:原有weatherdata函数中未导入from django.shortcuts import render,会导致报错。 - 数据库存储城市数据:相比每次读取JSON文件,用ORM查询数据库更高效,也符合Django的设计规范。
内容的提问来源于stack exchange,提问作者Adryan Taborda
相关产品推荐
相关产品推荐

