You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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),需要额外配置;服务端请求则没有这个问题,因为浏览器的跨域限制只针对前端请求。

服务端代码的优化建议

你现在的视图函数可以加一些优化:

  1. 异常处理:API请求可能失败(比如网络问题、股票代码错误),要加try-except块处理,避免页面崩溃。
  2. 缓存数据:比如用django.core.cache把股票的名称和价格缓存1小时,不用每次用户刷新页面都去调用API。
  3. 异步请求:如果用户持仓很多,同步请求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

火山引擎 最新活动