如何在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
相关产品推荐
相关产品推荐

