Django+Vue视频点播网站全栈开发实战与部署指南
简介:一款基于Django与Vue.js的视频点播平台源码,面向Python Web开发学习者和毕业设计选题者,覆盖视频分类展示、搜索、播放、后台管理、用户认证等核心功能,适合作为课程设计、毕业设计或企业级点播项目的基础工程。压缩包共462个文件、大小30.84MB,主要包括44个Python后端文件、40个Vue前端组件、49个ts切片及24个mp4样片,同时附带SQL数据库脚本、favicon图标、渲染图片和项目说明文档,便于快速搭建与理解整体结构。目前已有93人学习/下载。资源不仅提供完整可运行的前端Vue工程与后端Django工程,还包含可导入的SQL数据库脚本和示例媒体资源,方便本地搭建演示;配合源码中的目录组织,可深入理解Django模型设计、Vue组件通信、视频上传转码及静态资源部署等实践技巧,为课程设计、毕业设计或二次功能扩展提供直接参考。 毕业设计选了“基于Python的视频点播网站”这个题目,技术栈锁定Python + Django + Vue,说实话,这个组合在本科毕设里算是比较稳妥且上限很高的方案。做完了回头看,从环境搭建到前后端联调,再到视频分片播放,整个过程踩了不少坑,也积累了一些值得分享的经验。这篇文章就围绕这个选题,把从零搭建一套视频点播平台的完整思路、核心实现、关键代码和常见问题一次性讲清楚。准备做同类题目的同学,或者对Django + Vue全栈开发感兴趣的朋友,这篇应该能帮你在动手前把整体路线摸透。
1. 毕业设计选题与整体架构设计
1.1 为什么选Python + Django + Vue这个组合
视频点播系统的本质是:视频文件的存储与管理、用户与权限体系、播放页面的呈现。这三个核心诉求对应到技术选型上,Python和Django负责后端业务逻辑和接口输出,Vue负责前端交互和播放器集成,分工非常清晰。
从毕设答辩的角度看,这个组合有几个隐形的加分点:一是Django自带Admin后台,可以快速展示数据管理能力;二是Vue的组件化开发让前端代码结构一目了然,论文里好写、好画图;三是DRF(Django REST Framework)写接口非常快,能把大量时间留给视频处理和播放器集成这种“看起来有技术含量”的部分。Python本身语法友好,调试生态成熟,遇到问题Stack Overflow上一搜一大把,不至于卡死在环境问题上。
另外说句实际的,这个技术栈对后续找工作或者考研复试也有帮助。Django的MTV架构、Vue的响应式原理、RESTful API设计,这些都是面试高频考点。毕设做完,这些知识点基本也能脱口而出。
1.2 前后端分离架构的核心思路
我采用的是前后端完全分离的开发模式:Django只提供RESTful API,不负责渲染HTML页面;Vue通过Axios请求接口获取数据,在浏览器端完成页面渲染。这样做的直接好处是:前端开发和后端开发可以并行推进,我白天写Django模型和接口,晚上写Vue组件,互不阻塞。
具体到项目结构上,目录规划大致是这样的:
vod_project/ # Django项目根目录
├── backend/ # 后端代码
│ ├── apps/ # 子应用:users, videos, comments
│ ├── vod_backend/ # Django主配置
│ └── media/ # 视频文件与封面存储
├── frontend/ # Vue前端项目
│ ├── src/
│ │ ├── views/ # 页面组件
│ │ ├── router/ # 路由配置
│ │ ├── store/ # Vuex状态管理
│ │ └── api/ # Axios接口封装
│ └── public/
└── docs/ # 论文相关文档
接口设计遵循RESTful规范,比如视频列表是GET /api/videos/,视频详情是GET /api/videos/{id}/,用户登录是POST /api/auth/login/。前后端只通过JSON交换数据,视频文件本身用单独的URL访问,不经过API层。
1.3 功能模块划分与数据库设计
视频点播系统的核心功能我做了四个模块:用户模块、视频模块、评论模块、后台管理模块。用Django的app机制拆分,每个app职责单一,后期拓展也方便。
数据库设计是这次项目中我花心思比较多的地方。视频表的设计直接决定了接口返回的数据结构,我最终确定了下面这些关键字段:
-
title:视频标题,CharField必填 -
cover:封面图URL,ImageField存储 -
video_url:视频播放地址,存储m3u8文件名或完整URL -
category:分类,Foreignkey关联分类表,用于首页分类筛选 -
play_count:播放量,IntegerField,用于热门排序 -
uploader:上传用户,Foreignkey关联用户表 -
created_at:上传时间,DateTimeField自动记录
用户表直接使用Django内置的User模型,再通过OneToOneField扩展一个Profile来存头像、个人简介等额外信息。评论表关联用户和视频两个外键,形成典型的“一对多”关系。这种设计的合理性在于:Django内置User模型经过多年生产环境验证,权限体系和Session管理都是现成的,没必要自己重复造轮子。
2. 核心技术拆解:打通Django后端
2.1 环境准备与Django项目初始化
环境配置这一步看似简单,实际上坑最多。Python版本建议直接上3.10或3.11,Django版本选择4.2 LTS,DRF选对应兼容的3.14+版本。别用最新的Django版本,有些第三方库兼容性还没跟上,毕设阶段没必要给自己找麻烦。
# 创建虚拟环境
python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
# 安装依赖
pip install django==4.2
pip install djangorestframework
pip install django-cors-headers
pip install Pillow # 图片处理,封面图必须
项目初始化后,按套路创建子应用,然后重点配置两件事:一是在 INSTALLED_APPS 里注册子应用和DRF、corsheaders;二是在 settings.py 里配置数据库连接、媒体文件路径和CORS白名单。
关于CORS配置,我刚开始开发时没配好,Vue请求接口直接被浏览器拦截,控制台报错烦人得很。解决方法是安装 django-cors-headers ,在Middleware里加上 CorsMiddleware ,然后设置 CORS_ALLOW_ALL_ORIGINS = True (开发阶段),生产环境再改成具体的域名白名单。
2.2 模型设计与Admin后台配置
视频表的模型代码看起来简单,但有几个细节值得注意。一是上传时间和更新时间要自动记录,二是播放量默认值为0,三是分类外键要设置 on_delete=models.SET_NULL 和 null=True ,避免分类删除后视频报错。
用Django内置的Admin后台做数据管理,只需要在 admin.py 里简单注册:
from django.contrib import admin
from .models import Video, Category
@admin.register(Video)
class VideoAdmin(admin.ModelAdmin):
list_display = ('title', 'category', 'play_count', 'created_at')
search_fields = ('title',)
list_filter = ('category',)
这一套配置下来,后台就能直接管理视频发布、分类维护、播放量查看。答辩演示的时候,打开后台展示数据管理能力,比干讲代码直观得多。
2.3 基于DRF的接口设计与调试技巧
视频列表接口和详情接口是前后端联调中最核心的部分,我用DRF的 ModelViewSet 实现:
from rest_framework import viewsets
from .models import Video
from .serializers import VideoSerializer
class VideoViewSet(viewsets.ModelViewSet):
queryset = Video.objects.filter(status='published').order_by('-created_at')
serializer_class = VideoSerializer
def retrieve(self, request, *args, **kwargs):
# 详情访问时播放量+1
video = self.get_object()
video.play_count += 1
video.save(update_fields=['play_count'])
return super().retrieve(request, *args, **kwargs)
播放量加一的逻辑写在 retrieve 方法里,就是在详情接口被调用时自动累加。实际生产环境不会这么做,会有并发问题,但毕设项目里这个量级的逻辑完全够用,也方便答辩时展示业务逻辑。
DRF自带的可交互API文档页面(浏览器访问接口URL时自动渲染)是个非常实用的功能,调试接口时不需要Postman也能快速验证参数。配合Django Debug Toolbar,能清楚看到每个接口执行了多少条SQL查询,对排查N+1问题很有帮助。
2.4 视频上传与Django媒体文件配置
视频文件比较特殊,单个体积动辄几十MB甚至上GB,直接走Django的请求体上传容易超时。我的做法是:后端接口接收上传请求,把文件流写入到媒体目录的 videos/ 子目录下,文件名用 uuid + 原始文件名 拼接,避免重名。
def handle_uploaded_file(file, sub_dir):
# 生成唯一文件名
ext = os.path.splitext(file.name)[1]
filename = f"{uuid.uuid4().hex}{ext}"
# 目标路径:media/videos/{filename}
path = os.path.join(settings.MEDIA_ROOT, sub_dir, filename)
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
return filename
媒体文件访问路径通过 urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 配置,开发环境下直接通过URL访问视频文件。生产环境则需要配Nginx的alias或location块。
3. 前端Vue3 + 播放器集成
3.1 Vue项目创建与路由设计
前端使用Vue3 + Vite,这是目前Vue生态最适合新项目的组合,构建速度快,开发体验好。项目创建我用的是 npm create vue@latest 这个命令,它会自动生成基于Vite的模板工程。关于Vue2还是Vue3的选择,虽然很多教学视频还在讲Vue2,但从实际应用和面试角度来看,Vue3的组合式API是趋势,新项目直接用Vue3没毛病。
路由配置是前端的一个重点,我的路由结构如下:
const routes = [
{ path: '/', component: HomeView }, // 首页:视频列表
{ path: '/video/:id', component: VideoDetail }, // 视频详情页
{ path: '/category/:id', component: CategoryView }, // 分类页
{ path: '/login', component: LoginView }, // 登录注册页
{ path: '/admin', component: AdminView }, // 管理后台
]
路由守卫在视频点播系统里主要用来做登录验证,比如在管理后台和用户中心这些页面,判断 store 里有没有token,没有就跳转到登录页。值得提醒的是, Vue Router 还有很多高级用法比如路由懒加载、动态路由、嵌套路由,这些在毕设里不一定全用得上,但理解透了对后续做项目帮助很大。
3.2 m3u8视频播放:从vlc到hls.js
视频播放是前端最核心的部分。我最初直接用HTML5的 <video> 标签播mp4文件,本地测试没问题,但试了几次大文件之后发现两个问题:一是加载慢,二是拖动进度条时要缓冲很久。改用HLS协议(m3u8格式)后,这些问题明显改善。HLS的特点是自适应码率,会根据用户的网络状况自动选择清晰度。
播放m3u8的实现在Vue里非常简洁,用 hls.js 这个库:
npm install hls.js
然后在Vue组件里封装一个播放器,核心逻辑是:如果浏览器支持原生HLS,直接把 src 设为m3u8地址;如果不支持(比如大部分桌面浏览器),就用 hls.js 实例化并附加到video元素上。
import Hls from 'hls.js'
export function setupHls(videoEl, src) {
if (Hls.isSupported()) {
const hls = new Hls({ maxBufferLength: 30 })
hls.loadSource(src)
hls.attachMedia(videoEl)
return hls
}
}
3.3 视频分片处理实战:ffmpeg切片不焦虑
直接把mp4喂给hls.js也能播,但体验不是最佳。最好在管理端上传视频后,对视频做一遍分片转码处理,输出m3u8索引文件和对应的ts分片。这一步用ffmpeg命令行就能搞定:
ffmpeg -i input.mp4 -profile:v baseline -level 3.0 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls output.m3u8
解释一下几个关键参数: -hls_time 10 表示每个分片10秒, -hls_list_size 0 表示m3u8列表包含所有分片,不限制数量。 -profile:v baseline 是为了兼容性,用baseline profile能保证绝大多数设备都能解码播放。
切完片后,把整个目录(.m3u8文件 + .ts文件)放到媒体目录下,数据库中记录m3u8文件的URL路径,前端播放器拿到这个路径直接播。实测下来,拖动进度条几乎无感,体验提升非常明显。这些切片参数是我在开发过程中反复调试得出的,如果你处理时遇到播放卡顿或者列表过大的问题,优先检查这两个参数。
3.4 登录注册页面与Axios请求管理
登录注册模块是用户体系的前端实现。我做了用户名+密码的登录和注册表单,密码通过后端Django的认证系统校验,成功后返回token。前端把token存到localStorage和Vuex中,每次请求接口时通过Axios拦截器自动带在Authorization头部。
Axios封装是前端代码里的基础工程,我统一维护了一份配置:
const service = axios.create({
baseURL: '/api/v1',
timeout: 15000
})
// 请求拦截器:自动附加token
service.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
// 响应拦截器:统一处理错误码
service.interceptors.response.use(
res => res.data,
err => {
if (err.response?.status === 401) {
router.push('/login')
}
return Promise.reject(err)
}
)
这样统一管理的好处是,页面里只需要写 api.getVideoList() 这种语义化调用,不用每个组件都重复处理token和错误逻辑。代码量减少,且更规范。
4. 实操过程与问题排查:从联调到部署
4.1 前后端联调的代理配置
开发阶段前后端在不同端口运行(Vite默认5173,Django默认8000),直接跨域请求会被浏览器拦截是常态。其实,前后端联调核心就是解决跨域。我的做法有两个,配合使用体验最好:
第一,Django后端配置 django-cors-headers 允许跨域。第二,Vite开发服务器配置代理,把 /api 开头的请求转发到Django:
// vite.config.js
server: {
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
这里有一个开发经验值得强调:把代理配置好后,前端请求的baseURL统一写 /api ,不写完整的后端地址。这样切换到生产环境时,前端的请求代码一行都不用改,只需在生产服务器上把 /api 的反向代理配到Django即可。
4.2 常见报错与解决速查表
开发过程中遇到问题并解决问题的过程,本身就是毕设最有价值的部分。下面这些坑是我真实踩过的,整理成速查表供参考:
| 问题现象 | 原因分析 | 解决方案 |
|---|---|---|
| Vue请求接口报CORS错误 | 后端未配置允许跨域 | 安装django-cors-headers并配置白名单 |
| 视频播不了,视频元素时间轴无效 | mp4编码格式问题 | 转码为H.264编码的mp4,或切片成m3u8 |
| 上传大视频超时 | Django请求体大小限制 | 前端分片上传,或在Nginx层调大client_max_body_size |
| m3u8在Chrome里不能播 | Chrome不支持原生HLS | 用hls.js方案,兼容性更好 |
python migrate 报字段相关错误 | 模型修改后未生成对应迁移 | 按顺序执行makemigrations和migrate |
4.3 Linux服务器部署:麒麟和Nginx配置落地
出于国产化需求或题目特殊要求,某些学校用国产Linux系统(比如银河麒麟等支持国产芯片的Linux发行版)部署。在这些系统上部署Django和Vue,核心流程与Ubuntu等常见Linux发行版差异不大,但有几个易踩坑的地方需要特别注意。
第一个坑是Python环境。麒麟的软件源里自带的Python版本可能偏旧,直接装可能装不上较新的包。解决办法是先用 python3 --version 确认版本,版本过旧就从官网源码编译安装Python 3.10+。编译前记得先安装依赖:
sudo apt install -y build-essential libssl-dev zlib1g-dev libffi-dev
第二个坑是数据库。如果SQLite满足要求,直接用最省事;如果后续要求用MySQL或PostgreSQL,需要额外安装对应客户端库。对于毕设规模的项目,SQLite完全扛得住,部署在麒麟上时尽量不再引入额外数据库,降低环境复杂度。
部署架构采用Nginx + uWSGI/Gunicorn的标准组合。前端构建后生成 dist 静态文件目录,Nginx直接托管;后端用Gunicorn起Django服务,Nginx把 /api 和 /media 路径反向代理到8080端口:
server {
listen 80;
server_name your_domain_or_ip;
# 前端静态文件
root /path/to/frontend/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# 后端API反向代理
location /api/ {
proxy_pass http://127.0.0.1:8080/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 媒体文件访问
location /media/ {
alias /path/to/backend/media/;
}
}
这里的 try_files $uri $uri/ /index.html 是Vue路由history模式的关键配置,否则刷新页面会404。另外,媒体文件目录的权限也要注意,Nginx的工作进程(通常是 www-data )需要有读取该目录的权限,否则视频封面图加载不出来,这个坑很隐蔽。
4.4 Django在Linux服务器上常见的启动问题
Linux部署时Django本身也有几个经典问题。启动时Django报错找不到模块,大概率是虚拟环境没有正确激活,或pip安装的包在全局环境中找不到,解决方法是确保在虚拟环境下运行pip和gunicorn。
数据迁移也容易出问题。有时候在开发机上迁移成功,部署到服务器上却报找不到表。这是因为服务器上还没有执行迁移命令。请在服务器项目目录下按顺序执行 python manage.py migrate 。还有 collectstatic ,若Admin后台CSS样式丢失,多半是没执行这个命令收集静态文件。
给Django配一个开机自启的systemd服务比较稳妥,写简单unit文件即可,或者在进程每次被kill掉之后用 nohup 方式启动。如果你在Linux上不擅长复杂的进程管理工具,用最简单可靠的方式优先保证项目能按时演示。这些细节都搞定之后,整个系统在Linux上跑起来基本就顺畅了。
5. 功能优化与答辩准备建议
5.1 播放体验优化与SEO小技巧
播放体验是整个视频网站留住用户的命脉。除了分片,我还加了三个细节优化:封面图懒加载,列表页滚动时只加载视口附近的图片,用 IntersectionObserver 实现;播放进度记忆,用户离开视频页再回来时,直接从上次进度继续播,用localStorage记录播放位置;播放量榜和分类导航放首页显眼位置,让用户内容少走一步。这些细节成本低、见效快,也能丰富论文里的功能描述。
5.2 为毕设答辩增加几个亮点
答辩时老师通常会问几个关键问题:你这个系统解决了什么实际痛点?技术选型为什么这样选?有没有考虑过性能和安全?我在系统里埋了几个亮点,建议你也考虑进去。一是使用JWT做用户认证,比传统Session更轻量,答辩时可以讲清无状态认证的原理。二是引入Redis做缓存,把视频分类列表和热播榜单这类热点数据缓存起来,减轻数据库压力。三是对视频文件做了路径脱敏处理,数据库存的是加密文件名,防止直接通过URL遍历目录。这几个点虽然不是核心功能,但能体现你考虑问题的深度。
5.3 如果还有时间,这些功能可以继续做
毕设完成到这个程度已经可以交差了。如果想冲一把优毕或者展示更完整的工程能力,有几个扩展方向可以考虑:搜索功能,用Q对象对标题做模糊搜索,成本低且实用性强;视频评论的二级回复,在现有评论表上加一个 parent 自关联字段即可;个人中心加“收藏列表”,用多对多字段关联用户和视频。这些方向在工作量可控的前提下,能显著提升系统完整度。
6. 写在最后的经验心得
这套视频点播系统从零到一开发完成,我最大的感受是:毕设项目不在于技术多先进、功能多花哨,而在于把一条技术链路完整地打通,并且能讲清楚每个模块为什么这么设计。前后端分离、RESTful API、视频切片播放、Linux部署,这套流程走下来,对Web开发的理解和毕业设计开始前完全不是一个层级。
如果你也是这个题目,动手前一定先把开发环境搞定,Python的版本、Vue的Node版本要提前确认好,EOL版本经常会在装依赖时莫名报错。视频格式转换和播放器接入是最容易出现卡点的地方,建议第一周先把这两个环节做通跑通,后面往里面加功能会顺利不少。到了答辩前,优先保证基础流程能完整走通。很多同学答辩时在创建账号、上传视频、播放视频这条核心路径上出问题,演示卡壳,进度条转圈,老师一看就知道项目不扎实。核心路径走通,剩下的都是加分项。
最后再分享一个小技巧。做视频点播类项目时,准备一组画质好、尺寸适中、题材通用的测试视频,比如纪录片片段或电影预告片,配好封面图分类好。开发和演示的时候全套素材一步到位,用户在体验上不会觉得是个临时demo,给老师的印象分也能拉高不少。这套素材后续调试播放器、测试分片、做性能优化时都能反复复用,性价比极高。
更多推荐

所有评论(0)