1. 项目概述
这个基于Django的音乐推荐播放器项目是我最近完成的一个毕业设计作品,它结合了协同过滤算法来实现个性化音乐推荐功能。作为一个全栈开发者,我在这个项目中负责了从需求分析、架构设计到前后端开发的全流程工作。
项目采用了经典的B/S架构,前端使用Vue.js框架实现响应式界面,后端基于Django框架搭建RESTful API服务,数据库选用MySQL存储用户数据和音乐信息。最核心的部分是实现了基于用户的协同过滤推荐算法,能够根据用户的历史播放记录和相似用户的行为,生成个性化的音乐推荐列表。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术栈选型
在技术选型上,我经过多方比较最终确定了以下技术组合:
后端框架:Django
- 选择理由:Django作为Python生态中最成熟的Web框架,提供了完整的MVC架构和丰富的内置功能,特别适合快速开发数据驱动的应用。它的ORM层让数据库操作变得非常简单,内置的Admin后台也大大减少了管理界面的开发工作量。
前端框架:Vue.js
- 选择理由:Vue的轻量级和渐进式特性非常适合这个项目。它提供了响应式数据绑定和组件化开发体验,与Django后端可以很好地配合。特别是Vue的生态系统中有很多优秀的UI组件库,可以快速构建美观的界面。
数据库:MySQL
- 选择理由:作为最流行的开源关系型数据库,MySQL在性能、可靠性和社区支持方面都有很好的表现。对于音乐推荐系统来说,用户行为数据和音乐元数据的存储和查询需求都能很好地满足。
推荐算法:协同过滤
- 选择理由:协同过滤是推荐系统领域最经典和有效的算法之一,特别适合音乐推荐这种基于用户偏好的场景。实现相对简单但效果不错,适合作为毕业设计的算法实现。
2.2 系统架构图
整个系统采用了前后端分离的架构设计:
code复制┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ │ │ │ │ │
│ 客户端 │───▶│ Django │───▶│ MySQL │
│ (Vue.js) │◀───│ 后端 │◀───│ 数据库 │
│ │ │ │ │ │
└─────────────┘ └─────────────┘ └─────────────┘
前端通过HTTP请求与后端API交互,后端处理业务逻辑并访问数据库,最后将数据以JSON格式返回给前端渲染。
3. 核心功能实现
3.1 用户认证模块
用户系统是推荐系统的基础,我实现了完整的注册、登录和权限管理功能。
关键技术点:
- 使用Django内置的auth系统处理用户认证
- 通过JWT(JSON Web Token)实现无状态认证
- 密码采用PBKDF2算法加盐哈希存储
python复制# 用户注册视图示例
class RegisterView(APIView):
def post(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
# 设置密码并保存
user.set_password(serializer.validated_data['password'])
user.save()
return Response({"message": "注册成功"}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
3.2 音乐管理模块
音乐数据是系统的核心内容,我设计了以下数据结构:
音乐模型字段:
- id: 主键
- title: 歌曲名称
- artist: 艺术家
- album: 专辑
- duration: 时长(秒)
- release_date: 发行日期
- genre: 流派
- cover_url: 封面图URL
- audio_url: 音频文件URL
python复制class Music(models.Model):
title = models.CharField(max_length=100)
artist = models.CharField(max_length=100)
album = models.CharField(max_length=100)
duration = models.IntegerField() # 单位秒
release_date = models.DateField()
genre = models.CharField(max_length=50)
cover_url = models.URLField()
audio_url = models.URLField()
def __str__(self):
return f"{self.title} - {self.artist}"
3.3 协同过滤推荐算法
这是项目的核心创新点,我实现了基于用户的协同过滤算法:
算法实现步骤:
- 构建用户-音乐评分矩阵
- 计算用户相似度(使用余弦相似度)
- 找出目标用户的最近邻居(相似用户)
- 基于邻居用户的喜好预测目标用户可能喜欢的音乐
- 生成推荐列表
python复制def user_similarity(user1, user2):
"""计算两个用户的余弦相似度"""
common_musics = set(user1.ratings.keys()) & set(user2.ratings.keys())
if not common_musics:
return 0
# 计算向量点积
dot_product = sum(user1.ratings[m] * user2.ratings[m] for m in common_musics)
# 计算向量模
norm1 = sqrt(sum(r**2 for r in user1.ratings.values()))
norm2 = sqrt(sum(r**2 for r in user2.ratings.values()))
return dot_product / (norm1 * norm2)
def recommend_music(target_user, all_users, n=10):
"""为目标用户生成音乐推荐"""
# 计算与所有用户的相似度
similarities = [
(other_user, user_similarity(target_user, other_user))
for other_user in all_users if other_user != target_user
]
# 按相似度排序
similarities.sort(key=lambda x: x[1], reverse=True)
# 取前K个最相似用户
k_neighbors = similarities[:10]
# 收集邻居用户喜欢但目标用户未听过的音乐
recommendations = {}
for neighbor, sim in k_neighbors:
for music in neighbor.ratings:
if music not in target_user.ratings:
if music not in recommendations:
recommendations[music] = 0
recommendations[music] += neighbor.ratings[music] * sim
# 按推荐分数排序
sorted_recommendations = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)
return [music for music, score in sorted_recommendations[:n]]
4. 系统界面实现
4.1 前端架构
前端采用Vue CLI搭建项目骨架,主要依赖包括:
- Vue Router: 处理页面路由
- Vuex: 状态管理
- Axios: HTTP请求
- Element UI: UI组件库
项目目录结构:
code复制src/
├── assets/ # 静态资源
├── components/ # 公共组件
├── router/ # 路由配置
├── store/ # Vuex状态管理
├── views/ # 页面组件
├── App.vue # 根组件
└── main.js # 入口文件
4.2 主要页面实现
音乐播放页关键代码:
vue复制<template>
<div class="player-container">
<div class="cover">
<img :src="currentMusic.cover_url" alt="专辑封面">
</div>
<div class="info">
<h2>{{ currentMusic.title }}</h2>
<p>{{ currentMusic.artist }} - {{ currentMusic.album }}</p>
</div>
<audio
ref="audioPlayer"
:src="currentMusic.audio_url"
@timeupdate="updateProgress"
@ended="playNext"
></audio>
<div class="controls">
<button @click="togglePlay">{{ isPlaying ? '暂停' : '播放' }}</button>
<input
type="range"
v-model="progress"
@input="seek"
>
</div>
</div>
</template>
<script>
export default {
data() {
return {
currentMusic: {},
isPlaying: false,
progress: 0
}
},
methods: {
togglePlay() {
if (this.isPlaying) {
this.$refs.audioPlayer.pause()
} else {
this.$refs.audioPlayer.play()
}
this.isPlaying = !this.isPlaying
},
updateProgress() {
const audio = this.$refs.audioPlayer
this.progress = (audio.currentTime / audio.duration) * 100
},
seek(e) {
const audio = this.$refs.audioPlayer
audio.currentTime = (e.target.value / 100) * audio.duration
},
playNext() {
// 播放下一首逻辑
}
}
}
</script>
5. 系统测试与优化
5.1 功能测试
我设计了详细的测试用例来验证系统各功能模块:
用户认证测试用例:
- 注册新用户 - 验证用户名唯一性、密码强度
- 用户登录 - 验证凭证正确性
- 访问受保护路由 - 验证JWT有效性
推荐算法测试用例:
- 模拟用户行为数据
- 验证推荐结果的相关性
- 测试冷启动问题处理
5.2 性能优化
在实际测试中发现推荐算法在大用户量时性能下降,我做了以下优化:
- 相似度计算优化:引入稀疏矩阵和向量化计算
- 缓存机制:对频繁访问的用户相似度结果进行缓存
- 批量处理:将部分计算任务移到后台异步执行
python复制# 优化后的相似度计算
from scipy.sparse import csr_matrix
from sklearn.metrics.pairwise import cosine_similarity
def build_user_item_matrix(users):
"""构建用户-物品稀疏矩阵"""
user_ids = [u.id for u in users]
item_ids = list(set(i for u in users for i in u.ratings.keys()))
# 创建映射
user_idx = {uid: i for i, uid in enumerate(user_ids)}
item_idx = {iid: i for i, iid in enumerate(item_ids)}
# 构建矩阵
data = []
row = []
col = []
for user in users:
for item, rating in user.ratings.items():
data.append(rating)
row.append(user_idx[user.id])
col.append(item_idx[item])
return csr_matrix((data, (row, col))), user_idx, item_idx
def optimized_user_similarity(users):
"""优化后的用户相似度计算"""
matrix, user_idx, _ = build_user_item_matrix(users)
sim_matrix = cosine_similarity(matrix)
# 转换为字典形式
similarity = {}
for i, user1 in enumerate(users):
similarity[user1.id] = {}
for j, user2 in enumerate(users):
if i != j:
similarity[user1.id][user2.id] = sim_matrix[i][j]
return similarity
6. 部署方案
项目采用Docker容器化部署,便于环境一致性和扩展性:
Dockerfile示例:
dockerfile复制# 后端Dockerfile
FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "music_rec.wsgi:application"]
# 前端Dockerfile
FROM node:14 as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build-stage /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
docker-compose.yml配置:
yaml复制version: '3'
services:
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: music_rec
volumes:
- db_data:/var/lib/mysql
backend:
build: ./backend
ports:
- "8000:8000"
depends_on:
- db
environment:
DB_HOST: db
DB_NAME: music_rec
DB_USER: root
DB_PASSWORD: root
frontend:
build: ./frontend
ports:
- "8080:80"
volumes:
db_data:
7. 开发经验总结
在完成这个项目的过程中,我积累了一些宝贵的经验:
- Django ORM优化:对于频繁查询的模型,使用select_related和prefetch_related减少数据库查询次数
- Vue性能优化:合理使用v-if和v-show,避免不必要的组件渲染
- 推荐算法实践:协同过滤算法在实际应用中需要考虑冷启动和数据稀疏性问题
- 前后端协作:定义清晰的API文档和数据结构可以大大提高开发效率
这个项目让我对全栈开发有了更深入的理解,特别是在处理复杂业务逻辑和算法实现方面获得了宝贵的实战经验。对于想要学习Django和推荐系统的同学,我有几点建议:
- 先从Django官方教程开始,理解MTV架构
- 推荐系统方面可以先学习基础的协同过滤和内容推荐算法
- 实际开发中要注意性能优化,特别是数据库查询和算法计算
- 测试驱动开发(TDD)可以大大提高代码质量
