简介:一款基于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,给老师的印象分也能拉高不少。这套素材后续调试播放器、测试分片、做性能优化时都能反复复用,性价比极高。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

Logo

邀请您加入社区

更多推荐