如何将外部API返回的JSON数据存入Django模型以减少请求提升加载速度
实现方案
核心逻辑为定时异步拉取外部API数据存储到本地模型,用户请求直接读取本地数据,完全避免用户访问时调用外部接口,具体操作步骤如下:
1. 新增BTC价格存储模型
修改models.py,新增专门存储不同地区BTC价格的模型,同时修复原有Task模型的小问题(IntegerField不能直接作为字符串返回):
from django.db import models class Task(models.Model): title=models.IntegerField() completed=models.BooleanField(default=False) created=models.DateTimeField(auto_now_add=True) def __str__(self): # 修复原代码int类型直接返回的报错问题 return str(self.title) class BTCPrice(models.Model): # 地区标识,区分uk/ves region = models.CharField(max_length=10, unique=True) # 当前价格 current_price = models.FloatField() # 平均价格 average_price = models.FloatField() # 数据最后更新时间 updated_at = models.DateTimeField(auto_now=True) class Meta: db_table = "btc_price"
修改后执行python manage.py makemigrations和python manage.py migrate完成表结构创建。
2. 配置定时任务定期拉取API更新本地数据
选择轻量的django-apscheduler实现定时任务,无需额外依赖中间件:
- 安装依赖:
pip install django-apscheduler - 在
settings.py的INSTALLED_APPS中添加'django_apscheduler',执行迁移python manage.py migrate生成定时任务相关表 - 项目根目录新建
tasks.py编写更新逻辑:
from apscheduler.schedulers.background import BackgroundScheduler from django_apscheduler.jobstores import DjangoJobStore, register_events from .models import BTCPrice # 导入你原有的价格获取函数 from .utils import get_price_uk, get_average_price_uk, get_price_ves, get_average_price_ves def update_btc_price(): # 更新UK地区价格,存在就更新,不存在就新建 BTCPrice.objects.update_or_create( region="uk", defaults={ "current_price": get_price_uk(), "average_price": get_average_price_uk() } ) # 更新VES地区价格 BTCPrice.objects.update_or_create( region="ves", defaults={ "current_price": get_price_ves(), "average_price": get_average_price_ves() } ) # 启动定时任务,可根据价格时效性调整更新间隔,示例为5分钟更新一次 def start_scheduler(): scheduler = BackgroundScheduler() scheduler.add_jobstore(DjangoJobStore(), "default") scheduler.add_job(update_btc_price, 'interval', seconds=300, id="update_btc_price", replace_existing=True) register_events(scheduler) scheduler.start()
- 在项目的
wsgi.py末尾添加定时任务启动逻辑,保证项目启动时定时任务自动运行:
from your_app_name.tasks import start_scheduler start_scheduler()
3. 修改视图逻辑,直接读取本地数据
修改views.py的index函数,完全移除请求时对外部API的调用:
from .models import BTCPrice from .tasks import update_btc_price def index(request): form = TaskForm() if request.method == 'POST': form = TaskForm(request.POST) if form.is_valid(): form.save() return redirect("index") tasks = Task.objects.all() # 直接读取本地存储的价格数据 uk_price = BTCPrice.objects.filter(region="uk").first() ves_price = BTCPrice.objects.filter(region="ves").first() # 兜底逻辑:项目首次启动无数据时临时拉取一次 if not uk_price or not ves_price: update_btc_price() uk_price = BTCPrice.objects.get(region="uk") ves_price = BTCPrice.objects.get(region="ves") context = { "task_form": form, "tasks": tasks, "precio_uk": uk_price.current_price, "average_uk": uk_price.average_price, "precio_ves": ves_price.current_price, "average_ves": ves_price.average_price, } return render(request, 'index.html', context)
可选优化
如果站点访问量较大,可额外给价格数据添加Django缓存(内存/Redis均可),进一步减少数据库查询开销,响应速度可以达到毫秒级。
内容的提问来源于stack exchange,提问作者Carlos Rodriguez
相关产品推荐
相关产品推荐

