Django静态文件环境下视频播放列表功能异常求助
问题描述
- 点击右侧播放列表中的视频,无法切换为主播放视频
- 视频进度条无法拖动选择播放起始位置,也无法回退播放
- 尝试直接使用src路径加载视频失败,推测问题与Django静态文件配置相关
相关代码
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>My Website</title> <link rel="icon" href="./favicon.ico" type="image/x-icon"> </head> <div class = "container5"> <div class="main-video-container"> <video {% load static %} src ="{% static "Chapter 3.1 Exercise 1-4.mp4" %}" loop controls class="main-video"></video> <h3 class="main-vid-title"> Properties of Parallel Lines Exercise 1-4</h3> </div> <div class="video-list-container" > <!-- This is where we keep adding videos to our list--> <div class="list active"> <video {% load static %} src="{% static "Chapter 3.1 Exercise 1-4.mp4" %}" class="list-video"></video> <h3 class="list-title">Properties of Parallel Lines Exercise 5-7</h3> </div> <div class="list"> <video {% load static %} src="{% static "Chapter 3.1 Exercise 5-7.mp4" %}" class="list-video"></video> <h3 class="list-title">Properties of Parallel Lines Exercise 5-7</h3> </div><div class="list"> <video {% load static %} src="{% static "Chapter 3.1 Exercise 5-7.mp4" %}" class="list-video"></video> <h3 class="list-title">Properties of Parallel Lines Exercise 5-7</h3> </div> <div class="list"> <video {% load static %} src="{% static "Chapter 3.1 Exercise 5-7.mp4" %}" class="list-video"></video> <h3 class="list-title">Properties of Parallel Lines Exercise 5-7</h3> </div> <div class="list"> <video {% load static %} src="{% static "Chapter 3.1 Exercise 5-7.mp4" %}" class="list-video"></video> <h3 class="list-title">Properties of Parallel Lines Exercise 5-7</h3> </div> <div class="list"> <video {% load static %} src="{% static "Chapter 3.1 Exercise 5-7.mp4" %}" class="list-video"></video> <h3 class="list-title">Properties of Parallel Lines Exercise 5-7</h3> </div> </div> </div> <style> *{ box-sizing: border-box; } .container5{ max-width: 1200px; margin:100px auto; display: flex; flex-wrap: wrap; align-items: flex-start; gap: 20px; } .container5 .main-video-container{ flex: 1 1 700px; border-radius: 5px; box-shadow: 0 5px 15px rgba(246, 5, 5, 0.557); background-color: rgb(255, 119, 0); padding:15px } .container5 .main-video-container .main-video{ margin-bottom: 7px; border-radius: 5px; width:100%; } .container5 .main-video-container .main-vid-title{ font-size: 20px; color: brown; } .container5 .video-list-container{ flex:1 1 350px; height: 485px; overflow-y:scroll ; border-radius: 5px; box-shadow: 0 5px 15px rgba(246, 5, 5, 0.557); background-color: rgb(255, 119, 0); padding:15px } .container5 .video-list-container::-webkit-scrollbar{ width: 10px; } .container5 .video-list-container::-webkit-scrollbar-track{ background-color: #fff; border-radius: 5px; } .container5 .video-list-container::-webkit-scrollbar-thumb{ background-color: #c71111; border-radius: 5px; } .container5 .video-list-container .list{ display: flex; align-items: center; gap:15px; padding:10px; background-color: #eee; } .container5 .video-list-container .list{ display: flex; align-items: center; gap: 15px; padding: 10px; background-color: #eee; cursor: pointer; border-radius: 5px; margin-bottom: 10px; } .container5 .video-list-container .list:last-child{ margin-bottom: 0; } .container5 .video-list-container .list.active{ background-color: #d70f0f; } .container5 .video-list-container .list.active .list-title{ color: #1d4736; } .container5 .video-list-container .list .list-video{ width:100px; border-radius: 5px; } .container5 .video-list-container .list .list-title{ font-size: 17px ; color: #444; } </style> </html>
JavaScript代码
let videoList = document.querySelectorAll('.video-list-container.list'); videoList.forEach(vid =>{ vid.onclick = () =>{ let src = vid.querySelector('.list-video').src; let title = vid.querySelector('.list-title').innerHTML; document.querySelector('.main-video-container .main-video').src = src; document.querySelector('.main-video-container .main-video').play(); document.querySelector('.main-video-container .main-vid-title').innerHTML = title; }; });
问题分析与解决方案
1. 播放列表无法切换主视频的问题
问题根源
JavaScript选择器错误:document.querySelectorAll('.video-list-container.list') 会匹配同时拥有video-list-container和list类的元素,但实际列表项是video-list-container下的.list子元素,正确选择器应为.video-list-container .list。原选择器找不到目标元素,导致点击事件未绑定成功。此外,原代码未处理列表项的active类切换,点击后无视觉反馈。
修复后的JavaScript代码
// 选择所有列表项 let videoList = document.querySelectorAll('.video-list-container .list'); videoList.forEach(vid => { vid.onclick = () => { // 移除所有列表项的active类 videoList.forEach(item => item.classList.remove('active')); // 给当前点击项添加active类 vid.classList.add('active'); // 获取视频地址和标题 let src = vid.querySelector('.list-video').src; let title = vid.querySelector('.list-title').textContent; // 更新主视频 const mainVideo = document.querySelector('.main-video-container .main-video'); mainVideo.src = src; mainVideo.play(); document.querySelector('.main-video-container .main-vid-title').textContent = title; }; });
2. 视频进度条无法拖动的问题
问题根源
Django开发服务器(runserver)默认不支持字节范围请求(Byte-Range Requests),而视频进度拖动需要浏览器发送这类请求来获取视频的部分内容。此外,静态文件配置不当也可能导致视频无法正常加载。
解决方案
方案一:开发环境自定义视频服务视图
自定义视图处理视频请求,添加Accept-Ranges响应头:
- 在项目的
views.py中添加代码:
import os from django.http import HttpResponse, Http404 from django.conf import settings from django.views.static import serve def serve_video(request, path): file_path = os.path.join(settings.STATIC_ROOT, path) if not os.path.exists(file_path): raise Http404("Video not found") response = serve(request, path, document_root=settings.STATIC_ROOT) response['Accept-Ranges'] = 'bytes' return response
- 在
urls.py中添加路由:
from django.urls import path from . import views urlpatterns = [ # 其他路由... path('videos/<path:path>', views.serve_video, name='serve_video'), ]
- 修改模板中的视频src:
<!-- 替换原static标签,使用自定义路由 --> <video src="{% url 'serve_video' 'Chapter 3.1 Exercise 1-4.mp4' %}" loop controls class="main-video"></video>
方案二:生产环境使用Whitenoise(推荐)
生产环境部署时,用Whitenoise提供静态文件服务,它默认支持字节范围请求:
- 安装Whitenoise:
pip install whitenoise - 在
settings.py中配置:
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', # 添加该行 # 其他中间件... ] STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') STATIC_URL = '/static/' # 启用压缩和缓存 STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
额外检查项
- 确保视频文件编码为浏览器支持的格式(如MP4使用H.264视频编码和AAC音频编码)
- 检查Django静态文件配置:
STATICFILES_DIRS是否包含视频所在文件夹,STATIC_ROOT在生产环境是否正确收集了静态文件 - 模板中
{% load static %}只需在最顶部加载一次,无需每个video标签重复加载
内容的提问来源于stack exchange,提问作者DemieCoding
相关产品推荐
相关产品推荐

