Django向React组件传递JSON数据及API请求位置咨询
问题解决:React数据映射错误 + API请求位置分析
先帮你搞定React组件里的数据映射问题,再聊聊API请求的位置选择~
一、修复React数据映射的问题
你的代码里有几个关键错误,导致无法正确渲染数据:
1. 正确传递JSON数据到React
你现在把data_response作为字符串传给了UserPosition组件(data='{{ data_response }}'),这会让props里的data变成一个字符串,而不是可操作的JSON对象。
推荐用Django的json_script过滤器来安全传递JSON:
修改dashboard.html:
<div id="app" /> {# 用json_script把数据转成安全的JSON格式,存到id为portfolio-data的script标签里 #} {{ data_response|json_script:"portfolio-data" }} <script type="text/babel"> // 从script标签里读取并解析JSON const portfolioData = JSON.parse(document.getElementById('portfolio-data').textContent); class App extends React.Component { render() { return ( <UserPosition data={portfolioData} /> ); } }
2. 正确遍历对象型数据
你的data_response是一个对象(键是股票代码,值是详情),不是数组,所以不能直接用map。需要先把对象转成可遍历的数组,比如用Object.entries()获取键值对数组。另外,React里要用className代替class,还有要正确获取props:
修改UserPosition组件:
class UserPosition extends React.Component { render() { // 把对象转成 [symbol, {name, price}] 的数组 const portfolioEntries = Object.entries(this.props.data); return ( <div className="row"> {portfolioEntries.map(([symbol, item]) => ( <div key={symbol} className="col-3"> <div className="asset__container flex flex-horizontal"> <div> <h4>{item.name}</h4> <p>代码: {symbol}</p> <p>价格: ${item.price}</p> </div> </div> </div> ))} </div> ); } }
这里加了key属性(必须用唯一值,股票代码刚好合适),把class换成了className,还把对象转成了可遍历的数组。
3. 额外小提示
如果你的Django模板里直接用{{ data_response }},会输出Python的字典格式(比如单引号),而JSON要求双引号,所以json_script过滤器会帮你处理这个格式问题,避免解析错误。
二、API请求应该放在服务端还是客户端?
强烈建议放在服务端(也就是你现在的做法),原因如下:
- 保护API密钥:AlphaVantage的API密钥如果放在前端代码里,任何人都能通过查看源码拿到,很容易被滥用导致你的密钥被限流甚至封禁。放在服务端的话,密钥完全隐藏,只有你的服务器知道。
- 控制请求频率:AlphaVantage有请求次数限制(免费版一般是5次/分钟,500次/天),如果放在前端,每个用户的操作都可能触发请求,很容易超出限制。放在服务端你可以加缓存(比如用Django的缓存框架把股票数据缓存一段时间),避免重复请求同一个股票的数据。
- 统一数据处理:服务端可以提前处理API返回的数据(比如处理缺失字段、格式转换),前端只需要拿到干净的数据直接渲染,不用在前端做复杂的错误处理。
- 避免跨域问题:如果前端直接请求AlphaVantage的API,可能会遇到跨域限制(CORS),需要额外配置;服务端请求则没有这个问题,因为浏览器的跨域限制只针对前端请求。
服务端代码的优化建议
你现在的视图函数可以加一些优化:
- 异常处理:API请求可能失败(比如网络问题、股票代码错误),要加try-except块处理,避免页面崩溃。
- 缓存数据:比如用
django.core.cache把股票的名称和价格缓存1小时,不用每次用户刷新页面都去调用API。 - 异步请求:如果用户持仓很多,同步请求API会让页面加载很慢,可以用Django的异步视图(async def)来并行请求多个API,提升速度。
示例优化后的views.py片段:
from django.core.cache import cache def dashboard(request): user = Profile.objects.get(user=request.user) positions = user.positions.all() data_response = {} for position in positions: # 先查缓存 cached_data = cache.get(f"stock_{position.symbol}") if cached_data: data_response[position.symbol] = cached_data continue try: # 请求基本信息 overview_response = requests.get( "https://www.alphavantage.co/query?function=OVERVIEW", params={"symbol": position.symbol, "apikey": key} ) overview_data = overview_response.json() name = overview_data["Name"] # 请求价格 price_response = requests.get( "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY", params={"symbol": position.symbol, "apikey": key} ) price_data = price_response.json() latest_date = next(iter(price_data["Time Series (Daily)"])) # 获取最新日期 price = price_data["Time Series (Daily)"][latest_date]["4. close"] position_data = {"name": name, "price": price} data_response[position.symbol] = position_data # 缓存1小时 cache.set(f"stock_{position.symbol}", position_data, 3600) except Exception as e: # 处理错误,比如给默认值或者跳过该股票 print(f"获取股票 {position.symbol} 数据失败: {e}") data_response[position.symbol] = {"name": position.symbol, "price": "N/A"} return render(request, "holdings/dashboard.html", {'data_response': data_response})
内容的提问来源于stack exchange,提问作者JSON_Derulo




