用DjangoVue从零搭建一个短视频推荐网站附完整源码和部署教程短视频平台的爆发式增长让个性化推荐成为技术热点。许多开发者想尝试构建自己的推荐系统却常被全栈开发的技术栈和算法集成门槛劝退。本文将手把手带你实现一个具备核心推荐功能的短视频网站涵盖从数据库设计到算法调优的全流程。不同于简单Demo我们会重点解决实际开发中遇到的跨域配置、性能优化和冷启动问题。1. 项目架构设计与技术栈选型现代Web开发早已进入前后端分离的时代。我们选择Django作为后端API服务框架主要看中其开箱即用的Admin管理系统和稳健的ORM层而Vue 3的组合式API写法能让前端逻辑更清晰。这种技术组合既保证了开发效率又能满足毕业设计或创业项目的技术深度要求。核心组件分工前端Vue 3 Pinia状态管理 Vite构建工具后端Django 4.2 Django REST Framework SimpleJWT认证数据库PostgreSQL支持JSON字段存储视频标签推荐算法Python的Surprise库实现协同过滤部署Nginx反向代理 Gunicorn应用服务器提示虽然MySQL更常见但PostgreSQL对JSON数据的原生支持能简化标签系统的实现2. 后端核心模块实现2.1 数据库模型设计短视频平台的核心数据关系体现在用户、视频和交互行为三个维度。我们在models.py中定义以下关键模型from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): watch_history models.JSONField(defaultlist) # 记录观看视频ID class Video(models.Model): title models.CharField(max_length200) uploader models.ForeignKey(User, on_deletemodels.CASCADE) tags models.JSONField(defaultlist) # 视频标签如[舞蹈,搞笑] view_count models.IntegerField(default0) class UserBehavior(models.Model): user models.ForeignKey(User, on_deletemodels.CASCADE) video models.ForeignKey(Video, on_deletemodels.CASCADE) behavior_type models.CharField( # 点赞/收藏/分享 max_length20, choicesBEHAVIOR_CHOICES) created_at models.DateTimeField(auto_now_addTrue)2.2 RESTful API开发使用DRF构建API时需要特别注意分页和过滤的配置这对推荐系统的性能影响很大# settings.py REST_FRAMEWORK { DEFAULT_PAGINATION_CLASS: rest_framework.pagination.PageNumberPagination, PAGE_SIZE: 10, DEFAULT_FILTER_BACKENDS: [ django_filters.rest_framework.DjangoFilterBackend ], DEFAULT_AUTHENTICATION_CLASSES: ( rest_framework_simplejwt.authentication.JWTAuthentication, ) }推荐接口的核心视图逻辑class RecommendView(APIView): permission_classes [IsAuthenticated] def get(self, request): # 获取用户历史行为数据 user_actions UserBehavior.objects.filter( userrequest.user).values_list(video_id, flatTrue) # 调用推荐算法后续章节实现 video_ids recommend_engine(user_actions) # 序列化返回结果 videos Video.objects.filter(id__invideo_ids) serializer VideoSerializer(videos, manyTrue) return Response(serializer.data)3. 推荐算法集成3.1 协同过滤实现在recommendations目录下创建算法模块# recommendations/algorithms.py from surprise import Dataset, KNNBasic from surprise.model_selection import train_test_split import pandas as pd def build_collaborative_filtering(): # 从数据库加载用户行为数据 behaviors UserBehavior.objects.all().values() df pd.DataFrame(list(behaviors)) # 转换数据格式 reader Reader(rating_scale(0, 1)) data Dataset.load_from_df( df[[user_id, video_id, behavior_weight]], reader) # 训练模型 trainset, testset train_test_split(data, test_size0.25) algo KNNBasic(k40, sim_options{user_based: True}) algo.fit(trainset) return algo3.2 冷启动解决方案新用户或新视频的冷启动问题可以通过以下策略缓解热门推荐当用户行为数据不足时返回近期热门视频def get_trending_videos(): return Video.objects.order_by(-view_count)[:100]标签传播基于视频标签的相似度推荐from sklearn.metrics.pairwise import cosine_similarity def tag_based_recommendation(video_id): target Video.objects.get(idvideo_id) all_videos Video.objects.exclude(idvideo_id) # 计算标签相似度 similarities [] for v in all_videos: sim cosine_similarity([target.tags], [v.tags])[0][0] similarities.append((v.id, sim)) return sorted(similarities, keylambda x: x[1], reverseTrue)[:10]4. 前端工程化实践4.1 Vue组件设计采用Composition API组织代码保持逻辑清晰script setup import { ref, onMounted } from vue import { useUserStore } from /stores/user const userStore useUserStore() const videos ref([]) const fetchRecommendations async () { const res await axios.get(/api/recommend/, { headers: { Authorization: Bearer ${userStore.token} } }) videos.value res.data } onMounted(() { fetchRecommendations() }) /script4.2 性能优化技巧视频懒加载video v-forvideo in videos :keyvideo.id :postervideo.cover_url preloadnone clickhandleVideoClick /video请求节流import { throttle } from lodash window.addEventListener(scroll, throttle(() { if (nearBottom()) loadMore() }, 500))5. 生产环境部署5.1 Nginx配置要点处理视频流媒体需要特别注意缓冲区配置server { listen 80; server_name yourdomain.com; location /media/ { alias /path/to/media/; # 视频文件缓存设置 expires 30d; add_header Cache-Control public; } location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }5.2 Gunicorn调优参数根据服务器CPU核心数设置worker数量gunicorn core.wsgi:application \ --workers $(($(nproc) * 2 1)) \ --bind 0.0.0.0:8000 \ --timeout 120 \ --keep-alive 56. 常见问题解决方案跨域问题在Django中安装django-cors-headers并配置# settings.py INSTALLED_APPS [corsheaders] MIDDLEWARE.insert(2, corsheaders.middleware.CorsMiddleware) CORS_ALLOWED_ORIGINS [ http://localhost:8080, https://yourdomain.com ]视频上传限制调整Django的文件大小限制DATA_UPLOAD_MAX_MEMORY_SIZE 1024 * 1024 * 100 # 100MB FILE_UPLOAD_MAX_MEMORY_SIZE 1024 * 1024 * 100在项目开发过程中最耗时的往往是前后端联调阶段。建议使用Postman先测试所有API接口再进入前端开发。当推荐效果不理想时可以尝试调整算法中的相似度计算方式比如将余弦相似度改为皮尔逊相关系数。