ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Django视频点播后台管理系统:模型、权限与Admin实战解析

Django视频点播后台管理系统:模型、权限与Admin实战解析 简介这是一份基于Django框架的视频点播后台管理系统设计源码面向Python Web入门及进阶开发者、毕业设计或课程设计人群旨在解决视频点播内容高效管理与安全传输的问题。系统基于流行的Django框架开发遵循MVC架构模式通过ORM操作数据库实现了视频信息增删改查、用户权限控制、视频上传与分组管理等功能前端采用响应式设计可兼容PC与移动端同时具备防范常见网络攻击的安全考虑。资源共包含43个文件压缩包仅1022KB。其中16个Python源码文件承载核心业务逻辑与视图处理12个字节码文件用于运行时缓存并保护源码7个XML配置文件负责数据库连接和应用参数1份SQL文件可直接导入数据表结构另有4张图片素材、2个文本说明及1个IDE配置等辅助内容。整体目录划分清晰模型、迁移、配置与静态资源分离便于根据目录结构快速定位和修改代码。目前已有281人学习下载。研读本套源码能够系统掌握Django后台管理界面定制、ORM模型设计、用户认证与权限控制、项目分模块管理等实战技能项目本身模块化程度高扩展难度低既适合作为个人学习Django框架的完整案例也可为企业视频点播后台的快速搭建提供设计参考。1. 做视频后台难的不是播放器而是内容和权限的组织做视频点播后台的人都知道播放器只是最外面一层真正拉开工作量的是视频怎么分组、谁有上传权限、不同格式的视频怎么在上传之后被正确管理。这套基于 Django 框架的视频点播后台管理系统把视频信息存储、检索、更新以及用户、权限、分组的管理全部收进模型层和 Django 自带 admin 后台里数据库初始化脚本、迁移记录和源码放在同一个包里。源码包含 14 个 Python 文件、12 个 pyc 字节码、7 个 XML 配置和一份 video.sql覆盖了内容管理类后台最常见的几个模块。它适合有一定 Python 基础、正在改造内容管理系统或者想学习 Django admin 落地方式的开发者。2. 拆解源码包从文件分工看懂 Django 后台的工程结构2.1 upload.zip 解压后每一类文件承担的角色解开 upload.zip目录结构并不复杂。back_admin 这个名字同时承担了 Django 项目目录和业务应用目录的角色在中小型项目里很常见虽然不够「标准」但能显著减少目录层级适合快速交付。所有核心逻辑集中在 back_admin 下的 models.py、admin.py、views.py、urls.py、settings.py 里uploads 和 avatar 目录则是运行时上传文件的落盘位置。文件/目录角色重点内容back_admin/models.py数据模型视频、分组表的字段定义back_admin/admin.py模型注册后台列表页与编辑页的呈现方式back_admin/views.py业务视图上传、播放、权限过滤逻辑back_admin/migrations/迁移记录0001_initial 到 0004 的建表轨迹video.sql数据库基准数据建库后可直接导入uploads/2019/11上传资源封面图等运行时文件manage.py管理入口启动、建表、建超级用户用命令解压和查看目录层级unzip upload.zip -d video_admin cd video_admin find . -maxdepth 3 -type d | sortunzip 的 -d 参数指定解压目标目录避免文件散落find 用 -maxdepth 3 限制深度只看前两层结构就能快速定位 settings.py、migrations 这些关键位置。注意 .idea 和pycache这类目录通常不应该提交到工程里这份源码明显是从本地项目整体打包的保留它们反而能看出原开发环境的一些信息比如pycache下的 cpython-37.pyc 就表明原作者运行的是 Python 3.7。2.2 settings.py 里需要改的三个配置拿到源码第一件事不是急着运行而是把配置过一遍。这份源码配套的是 MySQL 数据库因为项目里带了一份 video.sql这种结构通常意味着数据库结构已经固定代码里的 DATABASES 配置需要和 SQL 文件里的库名、账号保持一致DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: video, USER: root, PASSWORD: your_password, HOST: 127.0.0.1, PORT: 3306, } } MEDIA_URL /media/ MEDIA_ROOT os.path.join(BASE_DIR, uploads)ENGINE 指定 MySQL 驱动Django 会通过它生成对应方言的 SQLNAME 必须和导入 video.sql 时创建的数据库同名否则执行查询会报OperationalError: Unknown database video。MEDIA_ROOT 指向 uploads 目录所有上传的视频封面和临时资源都会落到这个路径下部署时这个目录需要单独配置读写权限。如果本地没有 MySQL也可以临时改成 SQLite但要注意字段类型差异ImageField、CharField 这类字段没有影响DateTimeField 的存储格式则略有不同。2.3 从迁移文件反推建表过程migrations 目录下保留着 0001_initial.py、0002_auto_20191113_1603.py、0003_auto_20191113_1613.py、0004_auto_20191113_1618.py 四个文件。从命名时间可以看出视频相关表在 2019 年 11 月 13 日下午短短十几分钟内经历了四轮调整。迁移文件是 Django 对表结构变更的版本记录不要直接修改已生成的迁移而是通过命令生成新的增量python manage.py makemigrations python manage.py migrate python manage.py startapp video_commentmakemigrations 只把模型变更写入迁移文件不真正操作数据库migrate 才会执行 DDL 建表或加字段。startapp 用于创建新的业务模块如果要在这个项目上加评论管理、公告管理这就是标准入口生成的新 app 需要手动加入 settings.py 的 INSTALLED_APPS。查看某个迁移文件里的具体操作可以直接用编辑器打开里面是依赖关系和 operations 列表字段变更、建索引、加外键都以代码形式保存在那儿。3. 模型与 admin 注册后台管理页面是怎么长出来的3.1 视频表、分组表、用户表的关系设计Django 后台能自动生成增删改查前提是先把模型定义好并注册到 admin。视频点播场景里最重要的三个模型是 Video、Category 和 Django 内置的 User。Category 做内容分组Video 通过外键关联 Category再用 uploader 外键关联 User。这样设计的直接好处是分组改名时只需更新一处所有视频自动同步。from django.db import models from django.contrib.auth.models import User class Category(models.Model): name models.CharField(max_length64, uniqueTrue) sort models.IntegerField(default0, help_text越小越靠前) def __str__(self): return self.name class Video(models.Model): title models.CharField(max_length200) category models.ForeignKey(Category, on_deletemodels.PROTECT, nullTrue, blankTrue) video_url models.CharField(max_length255) cover models.ImageField(upload_touploads/%Y/%m, nullTrue, blankTrue) uploader models.ForeignKey(User, nullTrue, on_deletemodels.SET_NULL) play_count models.PositiveIntegerField(default0) created_at models.DateTimeField(auto_now_addTrue) def __str__(self): return self.title这段代码是视频点播后台最常见的模型骨架标题、分组、地址、封面、上传人各占一个字段。字段类型参数含义titleCharField(200)视频标题列表页默认展示列categoryForeignKey关联分组PROTECT 禁止删除被引用的分组video_urlCharField(255)视频文件路径或外链coverImageField封面图按年/月自动分目录play_countPositiveIntegerField播放次数默认 0created_atDateTimeField(auto_now_addTrue)写入时自动取当前时间on_delete 参数值得细说。PROTECT 表示存在外键引用时阻止删除分组避免「分组删了视频还挂在空分组上」SET_NULL 表示用户被删除后视频记录保留uploader 置空。auto_now_add 只在 create 时赋值编辑时不会更新适合记录创建时间。3.2 ORM 查询与删除不要到处写原生 SQL日常业务里视频列表、搜索、批量删除都用 ORM 完成。Django 的 QuerySet 是懒加载的真正执行 SQL 是在迭代或取值的时候这个特性可以用来做分页和条件拼装hot_videos Video.objects.filter(play_count__gte100).order_by(-play_count)[:10] Video.objects.filter(category__name教程).delete()filter 返回 QuerySet可以继续链式调用play_count__gte 是「大于等于」的字段查询order_by(-play_count) 按播放量倒序。delete() 是批量删除返回一个字典例如{back_admin.Video: 3}表示删掉了 3 条视频。如果视频存在外键引用delete 会级联处理相关对象删除前最好先做 count 确认Video.objects.filter(id__in[3, 5, 7]).count()还有一个经常被忽略的查询场景按分组统计视频数。用 annotate 配合聚合函数from django.db.models import Count categories Category.objects.annotate(video_countCount(video)).filter(video_count__gt0) for c in categories: print(c.name, c.video_count)annotate 给每个 Category 动态挂上一个 video_count 字段用 video_count__gt0 过滤掉空分组。这套写法能直接用在后台统计页不需要额外写 SQL也避免了拼接字符串带来的注入风险。3.3 admin.py 注册两行代码换一个管理后台把模型注册到 admin 后Django 会自动生成列表页、编辑页、删除确认页。对于 Category 这种结构简单的字典表一行注册就够了Video 这种核心业务表建议用 ModelAdmin 定制from django.contrib import admin from .models import Video, Category admin.register(Video) class VideoAdmin(admin.ModelAdmin): list_display [title, category, uploader, play_count, created_at] list_filter [category] search_fields [title] admin.site.register(Category)注册后的后台直接可用列表页默认显示 list_display 里的字段右侧出现 category 筛选顶部出现 title 搜索框。Category 用 admin.site.register 注册走的是默认展示方式显示的是str的返回值。这一层写好后视图层只需要负责业务判断基础增删改查全部交给 admin这正是 Django 适合做内容管理后台的核心原因。4. 环境搭建把 video.sql 导入 MySQL跑通整个项目4.1 建库、导入、确认字符集拿到的 video.sql 是数据库基准脚本包含建表语句和初始数据。第一步是创建同名数据库并导入注意指定字符集否则导入时遇到中文和 emoji 会乱码或报错。mysql -u root -p CREATE DATABASE video DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE video; SOURCE /path/to/video.sql; show tables;utf8mb4 是 MySQL 对完整 Unicode 的支持视频标题里出现生僻字或 emoji 都不会出问题。SOURCE 命令后面跟绝对路径或相对路径都可以但 Windows 下不要把路径写成C:\path\video.sql反斜杠会被转义。导入后执行 show tables确认核心表都创建成功。这里可以核对表数量和 models.py 的迁移记录是否对得上如果 SQL 里表比迁移文件多通常说明项目后续手工改过库。4.2 迁移文件与已有数据库的冲突处理一个高频坑先导入了 video.sql再运行 migrate报错说表已存在。原因是 Django 的迁移文件里记录了建表操作migrate 会尝试执行一遍而 SQL 脚本已经把这些表建出来了。此时要用 --fake-initial 标记python manage.py migrate --fake-initial--fake-initial 的作用是检测到表已存在时不再执行建表语句直接把迁移记录写入 django_migrations 表。之后再做字段调整就可以正常 makemigrations 和 migrate。如果表结构被手工改过和 models.py 不一致migrate 会报字段缺失先手工对齐或重新生成迁移再同步。任何时候动库之前备份都不会多余mysqldump -u root -p video video_backup.sql4.3 Python 3.7 字节码与 mysqlclient 的兼容坑源码包里带了一堆 cpython-37.pyc这是 Python 3.7 的字节码Django 会在首次导入时优先使用但字节码和 Python 版本强绑定换解释器版本后会自动失效重新编译直接删除pycache目录也没有影响。驱动安装是最常见的一个坎。MySQL 配 Django正常做法是装 mysqlclientpip install mysqlclient在 macOS 或 Linux 上经常遇到编译错误报错大多是mysql_config not found需要先装 MySQL 开发头文件。如果不想折腾编译环境常见的替代方案是 pymysql在 settings.py 顶部加两行import pymysql pymysql.install_as_MySQLdb()这样 Django 通过 MySQLdb 名称引用到的实际是 pymysql。要注意 pymysql 的版本和 Django 版本兼容性Django 3.2 以后对 mysqlclient 版本有要求先 pip list 确认已装版本。跑通后访问 /admin 出现登录页说明数据库连接、迁移记录、静态文件都正常。4.4 创建超级用户并启动开发服务器python manage.py createsuperuser python manage.py runserver 0.0.0.0:8000runserver 的 0.0.0.0 让服务监听所有网卡局域网内其他机器可以通过 IP 访问方便联调。浏览器打开 http://127.0.0.1:8000/admin输入刚创建的账号。如果页面样式丢失优先检查 DEBUG 是否开启如果登录提示数据库错误回到 4.2 查看迁移状态。5. 视频上传、分组管理与多格式点播的落地细节5.1 上传目录与分年月存储策略uploads/2019/11 这种路径在源码里出现说明封面和上传资源按时间分目录存放。这个策略在文件数量变大后非常重要单个目录文件超过几千个文件系统遍历速度就会明显下降。Django 视图里处理上传的常见做法是import os from django.conf import settings from django.http import HttpResponse def upload_video(request): if request.method POST and request.FILES.get(video_file): f request.FILES[video_file] save_path os.path.join(settings.MEDIA_ROOT, f.name) with open(save_path, wb) as dest: for chunk in f.chunks(): dest.write(chunk) return HttpResponse(ok) return HttpResponse(POST with video_file)注意这里用的是 chunks() 而不是 read()。上传大文件时read() 会把整个文件读进内存多用户同时上传时服务很容易被打满chunks() 按块写入磁盘内存占用稳定。保存文件后还需要创建 Video 记录把 path 写入 video_url 字段这样才能在后台列表里看到并管理。MEDIA_ROOT 配置在前面 2.2 已经提到生产环境一般把 uploads 挂到独立磁盘或对象存储。5.2 多格式点播响应头决定播放还是下载视频点播的响应处理和普通下载不同。mp4、webm、m3u8 的 content_type 都不一样StreamingHttpResponse 可以逐块返回大文件配合 Content-Disposition 控制是内嵌播放还是强制下载from django.http import StreamingHttpResponse def stream_video(request, video_id): video Video.objects.get(idvideo_id) file_path video.video_url def chunk_file(): with open(file_path, rb) as f: while True: block f.read(1024 * 1024) if not block: break yield block resp StreamingHttpResponse(chunk_file(), content_typevideo/mp4) resp[Content-Disposition] finline; filename{video.title}.mp4 return respStreamingHttpResponse 接收的是可迭代对象生成器逐段产出数据避免大文件整体加载进内存。content_type 用于告知浏览器这是视频流浏览器会用内置播放器解析Content-Disposition 的 inline 表示页面内播放attachment 则会让浏览器下载文件。这一版是教学写法生产环境如果希望拖动进度条时响应秒开优先用 Django 的 FileResponse它对 HTTP Range 请求有内置支持客户端可以按字节区间拉取。移动端点播场景常见做法是转出 m3u8 切片再交给前端播放器加载。5.3 分组管理与权限过滤的查询写法用户管理和权限控制是视频后台的安全底线。Django 的权限系统会给每个模型生成 add、change、delete、view 四种权限判断当前用户能否查看视频常见写法是from django.shortcuts import get_object_or_404 def video_detail(request, video_id): video get_object_or_404(Video, idvideo_id) if request.user.has_perm(back_admin.view_video): return render(request, video_detail.html, {video: video}) return HttpResponseForbidden(无权限查看)has_perm 的参数格式是app_label.codenameback_admin 是 app 名view_video 是 Django 为 Video 模型自动生成的权限码。更细的业务分组比如「运营一组只看自己上传的视频」可以再叠加条件queryset Video.objects.all() if not request.user.is_superuser: queryset queryset.filter(uploaderrequest.user)超级用户跳过过滤普通用户只看自己上传的内容。需要注意别把业务分组和 Django auth 的 Group 混用auth 的 Group 负责权限授予业务上的分组用 Category 或自定义字段即可。5.4 模板层如何消费这些数据Django 模板负责展示视图只需要把 QuerySet 或 model 实例传给模板。列表页常见的片段是{% for video in videos %} div classvideo-item a href{% url video_detail video.id %}{{ video.title }}/a span{{ video.category.name }}/span span{{ video.play_count }} 次播放/span /div {% empty %} p暂无视频/p {% endfor %}{% url %} 标签通过视图名称反向生成链接比硬编码路径更稳妥视图改名或路径调整时不需要改模板。模板里访问外键字段用点号链式调用category.name 会自动触发 ORM 获取关联对象。这个片段不涉及复杂 JS符合本轮设计的后端管理定位。6. admin 后台列表页优化把默认页面改成业务操作台6.1 用 list_display、list_editable 与 list_filter 做减法Django admin 默认列表只显示模型str对操作人员来说信息量太少。调整 ModelAdmin 是优化成本最低的方案from django.contrib import admin from .models import Video admin.register(Video) class VideoAdmin(admin.ModelAdmin): list_display [id, title, category, uploader, play_count, created_at] list_editable [play_count] list_filter [category, uploader] search_fields [title, video_url] list_per_page 20 readonly_fields [created_at]这段配置能带来几个直接变化id 列方便和数据表对照play_count 进入 list_editable 后不用点进详情页就能修改展示数值list_filter 在右侧渲染筛选面板search_fields 决定顶部搜索框匹配哪些字段。readonly_fields 用于保护创建时间这类不允许运营改动的字段。6.2 用 list_select_related 消除后台 N1 查询后台列表渲染一行就要查询一次外键当列表页展示 category 和 uploader 时默认会有 N1 次查询。数据量上千后页面会明显变慢解决办法是让 Django 用 JOIN 把关联表提前查出来class VideoAdmin(admin.ModelAdmin): list_select_related [category, uploader]list_select_related 是 ModelAdmin 的内置属性添加后列表查询会一次性带出外键对象。这一步不需要改视图代码后台响应速度的提升却是实打实的。如果再用 django-debug-toolbar 的 SQL 面板核对查询数量会从 N 次降为 1 次。刷新 /admin/video/video/ 页面列表加载、筛选和搜索的响应速度会立刻有感知。本文还有配套的精品资源点击获取
返回列表