Django网站加载慢:如何先加载空模板再异步填充热门股票数据?
解决方案:异步加载Django页面数据提升初始加载速度
嘿,作为Django新手碰到页面初始加载慢的问题太正常啦!你的核心需求是先让页面快速渲染出来,再异步填充股票数据,咱们一步步来实现这个方案~
1. 简化原视图,快速返回基础页面
原来的视图会同步请求多个第三方API,必须等所有请求完成才会返回页面,这就是加载慢的根源。现在咱们把这部分逻辑砍掉,让视图直接返回不带股票数据的页面:
from jinja2 import Environment, FileSystemLoader from django.http import HttpResponse def index(request): env = Environment(loader=FileSystemLoader('templates')) template = env.get_template('index.html') # 只传递空的股票列表,模板里要做好空数据的兼容处理 template_values = {'popular_stocks': []} return HttpResponse(template.render(template_values))
2. 创建独立API视图,提供股票数据
接下来咱们写一个专门处理股票数据请求的视图,它只负责获取并返回JSON格式的股票数据,供前端异步调用:
from django.http import JsonResponse from tools import fetcher import requests import json def get_popular_stocks(request): popular = fetcher.get_tops() popular_stocks = [] for instrument in popular: try: # 用f-string让代码更简洁 r = requests.get(f'https://api.iextrading.com/1.0/stock/{instrument["symbol"]}/quote') r.raise_for_status() # 捕获HTTP请求错误 quote = json.loads(r.content.decode('utf-8')) popular_stocks.append(quote) except Exception as e: # 出错时可以记录日志,或者直接跳过该股票 print(f"获取股票{instrument['symbol']}数据失败: {str(e)}") continue # safe=False是因为返回的是列表而非字典 return JsonResponse(popular_stocks, safe=False)
3. 配置URL路由,让前端能访问API
在你的项目urls.py里添加新的路由,把刚才的API视图映射到一个可访问的URL:
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), # 新增API路由,前端会通过这个地址请求数据 path('api/popular-stocks/', views.get_popular_stocks, name='popular-stocks-api'), ]
4. 修改前端模板,实现AJAX异步加载
最后在index.html里,先预留一个容器用来展示股票数据,再用JavaScript在页面加载完成后异步请求API并渲染数据。这里提供两种实现方式:
原生JavaScript版本(无需额外依赖)
<!-- 预留数据展示容器,先放加载提示 --> <div id="popular-stocks-container"> <p>正在加载热门股票数据...</p> </div> <script> // 页面DOM加载完成后执行 document.addEventListener('DOMContentLoaded', function() { const container = document.getElementById('popular-stocks-container'); // 发送异步请求 fetch('/api/popular-stocks/') .then(response => { if (!response.ok) throw new Error('数据请求失败'); return response.json(); }) .then(data => { // 清空加载提示 container.innerHTML = ''; if (data.length === 0) { container.innerHTML = '<p>暂无热门股票数据</p>'; return; } // 动态生成股票列表HTML const stockList = document.createElement('ul'); data.forEach(stock => { const listItem = document.createElement('li'); // 格式化显示股票信息,涨跌百分比用正负号区分 listItem.innerHTML = `<strong>${stock.symbol}</strong>: $${stock.latestPrice} (${stock.changePercent > 0 ? '+' : ''}${stock.changePercent.toFixed(2)}%)`; stockList.appendChild(listItem); }); container.appendChild(stockList); }) .catch(error => { container.innerHTML = `<p>加载失败:${error.message}</p>`; }); }); </script>
jQuery版本(如果项目已引入jQuery)
<div id="popular-stocks-container"> <p>正在加载热门股票数据...</p> </div> <script> $(document).ready(function() { const $container = $('#popular-stocks-container'); $.ajax({ url: '/api/popular-stocks/', method: 'GET', dataType: 'json', success: function(data) { $container.empty(); if (data.length === 0) { $container.html('<p>暂无热门股票数据</p>'); return; } let $stockList = $('<ul></ul>'); $.each(data, function(index, stock) { const changeSign = stock.changePercent > 0 ? '+' : ''; const $listItem = $(`<li><strong>${stock.symbol}</strong>: $${stock.latestPrice} (${changeSign}${stock.changePercent.toFixed(2)}%)</li>`); $stockList.append($listItem); }); $container.append($stockList); }, error: function(xhr, status, error) { $container.html(`<p>加载失败:${error}</p>`); } }); }); </script>
额外优化建议
- 缓存第三方API数据:股票数据不会实时高频变化,用Django缓存框架缓存API结果,比如缓存5分钟,避免重复请求第三方API:
from django.core.cache import cache def get_popular_stocks(request): # 先从缓存取数据 cached_data = cache.get('popular_stocks') if cached_data: return JsonResponse(cached_data, safe=False) # 原来的获取数据逻辑... # 缓存数据,过期时间300秒(5分钟) cache.set('popular_stocks', popular_stocks, 300) return JsonResponse(popular_stocks, safe=False) - 批量请求第三方API:如果
fetcher.get_tops()返回大量股票符号,看看第三方API是否支持批量查询,一次请求多个股票数据,减少HTTP请求次数。
内容的提问来源于stack exchange,提问作者APorter1031
相关产品推荐
相关产品推荐

