You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django项目中集成React并传递Spotify API数据

解决方案

一、将React集成到Django项目

1. 初始化React项目

在Django项目根目录下,运行以下命令创建React项目:

npx create-react-app frontend

2. 配置Django静态文件

修改Django项目的settings.py,添加静态文件路径:

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    BASE_DIR / 'frontend/build/static',
]
STATIC_ROOT = BASE_DIR / 'staticfiles'

3. 配置Django视图提供React入口

开发环境

让React启动自身开发服务器(默认3000端口),并在React的package.json中添加代理配置,将API请求转发到Django(8000端口):

// frontend/package.json
"proxy": "http://localhost:8000"

生产环境

运行npm run build生成React生产构建文件,然后在Django中添加视图返回React的index.html:

from django.views.generic import TemplateView

class ReactAppView(TemplateView):
    template_name = 'index.html'

将frontend/build/index.html复制到Django的templates目录下即可。

二、将Spotify数据传递给React应用

方法1:初始渲染时通过模板传递(服务端渲染方式)

修改top_track视图,把track_info转成JSON格式传给模板:

import json

def top_track(request):
    # ... 原有代码 ...

    # 将track_info转为JSON字符串
    top_tracks_json = json.dumps(track_info)

    return render(request, "top_tracks.html", {
        "top_tracks": track_info, 
        "time_frame": time_frame, 
        "timeframe" : timeframe,
        "top_tracks_json": top_tracks_json
    })

在模板中把JSON数据赋值给全局变量,供React读取:

<!-- 在模板末尾添加 -->
<script>
window.topTracksData = {{ top_tracks_json|safe }};
window.currentTimeFrame = "{{ time_frame }}";
</script>
<!-- 引入React打包文件 -->
<script src="{% static 'js/main.xxx.js' %}"></script>

React组件中直接读取全局变量:

// frontend/src/components/TopTracks.js
import { useState } from 'react';

function TopTracks() {
  const [tracks] = useState(window.topTracksData);
  const [timeframe] = useState(window.currentTimeFrame === 'short_term' ? '1 Month' : window.currentTimeFrame === 'medium_term' ? '6 Months' : 'All Time');

  return (
    <div>
      <h1>Your Top Tracks - {timeframe}</h1>
      <ul className="track-grid">
        {tracks.map(item => (
          <li key={item.track.id}>
            <img src={item.album_cover} alt="Album Cover" />
            <figcaption><strong>{item.track.name}</strong> by {item.artist_name}</figcaption>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default TopTracks;

方法2:通过Django API接口传递(前后端分离方式)

步骤1:创建Django API视图

先安装Django REST Framework:

pip install djangorestframework

在settings.py中添加'rest_framework'到INSTALLED_APPS,然后编写API视图:

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
import spotipy
from spotipy.oauth2 import SpotifyOAuth
from django.conf import settings

class TopTracksAPI(APIView):
    def get(self, request):
        code = request.session.get('spotify_code')
        time_frame = request.GET.get('time_frame', 'short_term')
        limit_frame = request.GET.get('limit_frame', 20)
        if not code:
            return Response({"error": "No Spotify code found"}, status=400)
        
        spotify_auth = SpotifyOAuth(
            client_id=settings.SPOTIPY_CLIENT_ID,
            client_secret=settings.SPOTIPY_CLIENT_SECRET,
            redirect_uri=settings.SPOTIPY_REDIRECT_URI,
        )
        token_info = spotify_auth.get_access_token(code)
        access_token = token_info['access_token']
        sp = spotipy.Spotify(auth=access_token)

        top_tracks = sp.current_user_top_tracks(limit=limit_frame, time_range=time_frame)
        track_info = []
        for track in top_tracks['items']:
            track_id = track['id']
            album = sp.track(track_id)['album']
            album_cover = album['images'][0]['url'] 
            artist_name = track['artists'][0]['name']    
            track_info.append({
                'track': track,
                'album_cover': album_cover,
                'artist_name' : artist_name,
            })
        
        timeframe_label = "1 Month" if time_frame == "short_term" else "6 Months" if time_frame == "medium_term" else "All Time"
        return Response({
            "top_tracks": track_info,
            "time_frame": time_frame,
            "timeframe": timeframe_label
        })

在urls.py中添加API路由:

from django.urls import path
from .views import TopTracksAPI

urlpatterns = [
    # ... 其他路由 ...
    path('api/top-tracks/', TopTracksAPI.as_view(), name='top_tracks_api'),
]

步骤2:React中请求API获取数据

在React组件中使用fetch请求API:

// frontend/src/components/TopTracks.js
import { useState, useEffect } from 'react';

function TopTracks() {
  const [tracks, setTracks] = useState([]);
  const [timeframe, setTimeframe] = useState('1 Month');
  const [currentTimeFrame, setCurrentTimeFrame] = useState('short_term');
  const [limit, setLimit] = useState(20);

  useEffect(() => {
    fetch(`/api/top-tracks/?time_frame=${currentTimeFrame}&limit_frame=${limit}`)
      .then(res => res.json())
      .then(data => {
        setTracks(data.top_tracks);
        setTimeframe(data.timeframe);
      })
      .catch(err => console.error(err));
  }, [currentTimeFrame, limit]);

  const handleTimeFrameChange = (newTimeFrame) => {
    setCurrentTimeFrame(newTimeFrame);
  };

  const handleLimitChange = (newLimit) => {
    setLimit(newLimit);
  };

  return (
    <div>
      <h1>Your Top Tracks - {timeframe}</h1>
      <ul className="track-grid">
        {tracks.map(item => (
          <li key={item.track.id}>
            <img src={item.album_cover} alt="Album Cover" />
            <figcaption><strong>{item.track.name}</strong> by {item.artist_name}</figcaption>
          </li>
        ))}
      </ul>
      <button onClick={() => handleTimeFrameChange('short_term')}>1 Month</button>
      <button onClick={() => handleTimeFrameChange('medium_term')}>6 Months</button>
      <button onClick={() => handleTimeFrameChange('long_term')}>All Time</button>
      <button onClick={() => handleLimitChange(20)}>Top 20 Tracks</button>
      <button onClick={() => handleLimitChange(50)}>Top 50 Tracks</button>
    </div>
  );
}

export default TopTracks;

内容的提问来源于stack exchange,提问作者KL02

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 15:54:52