从本讲开始,我们开始视频管理功能的开发,视频管理包括视频上传、视频列表、视频编辑、视频删除。另外还有视频分类的功能,会一同讲解。这一讲非常重要,因为你将学习到一些之前没有学过的技术,比如大文件上传技术。

视频上传

我们先来实现视频的上传,视频的上传采用的是分块上传的策略,并用了分块上传类库:django_chunked_upload,使用该类库,再配合前端上传js库(jquery.fileupload.js),即可完美的实现文件的分块上传功能。

照例先编写添加视频的路由

添加视频,当然需要上传视频的页面,我们的页面是video_add路由来显示,通过urls .py中指定

path('video_add/', views.AddVideoView.as_view(), name='video_add'),

AddViewView仅仅用来显示上传页面,它的代码很简单

class AddVideoView(SuperUserRequiredMixin, TemplateView):template_name = 'myadmin/video_add.html'

只是继承了TemplateView来显示myadmin/video_add.html

myadmin/video_add.html中实现了上传视频的全过程,视频的上传采用的是分块上传的策略,前端使用的是js上传库(jquery.fileupload.js),后端使用的是django_chunked_upload,上传的逻辑是这样的:前端先选择一个文件,通过jquery.fileupload.js中的$.fileupload()方法来上传文件,后端接收到后分批返回已上传块的进度,前端根据进度来更新界面。由于上传前需要做一些校验的操作,代码较复杂,所以我们把上传的代码封装到了一个js中:static/js/myadmin/video_upload.js,主要的代码如下:


$("#chunked_upload").fileupload({url: api_chunked_uplad,dataType: "json",maxChunkSize: 100000, // Chunks of 100 kBformData: form_data,add: function(e, data) { // Called before starting uploadvar fileSize = data.originalFiles[0]['size'];var type = data.originalFiles[0]['type']; if(fileSize > 100000000){alert('文件太大了,请上传100M以内的文件');return;}if(!type.startsWith("video/")){alert('视频格式不正确');return;}form_data.splice(1);calculate_md5(data.files[0], 100000);  // Again, chunks of 100 kBdata.submit();$('#progress_label').on('click', false);$('#progress_layout').show()},chunkdone: function (e, data) { // Called after uploading each chunkif (form_data.length < 2) {form_data.push({"name": "upload_id", "value": data.result.upload_id});}var progress = parseInt(data.loaded / data.total * 100.0, 10);console.log(progress);if(progress > lastprogress){lastprogress = progress$('#upload_progress').progress({percent: progress});}},done: function (e, data) { // Called when the file has completely uploaded$.ajax({type: "POST",url: api_chunked_upload_complete,data: {csrfmiddlewaretoken: csrf,upload_id: data.result.upload_id,md5: md5},dataType: "json",success: function(data) {console.log(data)$('#upload_label').text('上传成功');$('#upload_progress').progress({percent: 100});$('#next_layout').show();$('#next').click(function(){window.location = '/myadmin/video_publish/' + data.video_id});}});},
});

在$.fileupload()方法中,有一个回调方法chunkdone(),该方法是用来更新进度的,告诉前端已经上传了多少字节。另外还有一个回调方法done(),该方法表示上传完毕,前端可在里面做一些额外的事情。

上传完毕后,调用了一个接口api_chunked_upload_complete,来给后端发送一个回执:我已上传完毕。

api_chunked_upload和api_chunked_upload_complete的路由是

path('chunked_upload/',  views.MyChunkedUploadView.as_view(), name='api_chunked_upload'),
path('chunked_upload_complete/', views.MyChunkedUploadCompleteView.as_view(),name='api_chunked_upload_complete'),

在MyChunkedUploadCompleteView中,我们在利用Video模型创建了这条视频

class MyChunkedUploadCompleteView(ChunkedUploadCompleteView):model = MyChunkedUploaddef get_response_data(self, chunked_upload, request):video = Video.objects.create(file=chunked_upload.file)return {'code': 0, 'video_id': video.id, 'msg': 'success'}

上传完毕效果如下

然后用户点击下一步,进入video_publish页面,开始发布前的资料填写

video_publish的路由是

path('video_publish/<int:pk>/', views.VideoPublishView.as_view(), name='video_publish'),

video_publish的视图类是VideoPublishView,它的代码如下

class VideoPublishView(SuperUserRequiredMixin, generic.UpdateView):model = Videoform_class = VideoPublishFormtemplate_name = 'myadmin/video_publish.html'def get_context_data(self, **kwargs):context = super(VideoPublishView, self).get_context_data(**kwargs)clf_list = Classification.objects.all().values()clf_data = {'clf_list':clf_list}context.update(clf_data)return contextdef get_success_url(self):return reverse('myadmin:video_publish_success')

对应的页面是myadmin/video_publish.html

就是下面这个页面

要填写的视频资料有视频标题、描述、分类、封面,

其中分类是通过get_context_data()带过来的,

填写后,点击发布,django将通过UpdateView自动为你更新视频信息。并通过get_success_url跳转到成功页面myadmin:video_publish_success,它的路由是

path('video_publish_success/', views.VideoPublishSuccessView.as_view(), name='video_publish_success'),

对应VideoPublishSuccessView是

class VideoPublishSuccessView(generic.TemplateView):template_name = 'myadmin/video_publish_success.html'

如下

我们点击视频列表即可查看视频

视频列表

视频列表的路由是

path('video_list/', views.VideoListView.as_view(), name='video_list'),

对应的视图类是VideoListView

class VideoListView(AdminUserRequiredMixin, generic.ListView):model = Videotemplate_name = 'myadmin/video_list.html'context_object_name = 'video_list'paginate_by = 10q = ''def get_context_data(self, *, object_list=None, **kwargs):context = super(VideoListView, self).get_context_data(**kwargs)paginator = context.get('paginator')page = context.get('page_obj')page_list = get_page_list(paginator, page)context['page_list'] = page_listcontext['q'] = self.qreturn contextdef get_queryset(self):self.q = self.request.GET.get("q", "")return Video.objects.get_search_list(self.q)

这里继承了ListView来显示视频列表,并通过get_queryset实现了搜索功能,通过get_context_data()实现了分页功能。

最后展示效果如下

你可能会发现,页面中还有编辑和删除的功能。编辑呢,是对单个视频对资料进行更新,删除即删除本条视频和视频文件。

视频编辑

我们先实现编辑功能,路由是

path('video_edit/<int:pk>/', views.VideoEditView.as_view(), name='video_edit'),

对应对视图类是VideoEditView,这个视图类是需要传递主键的。

class VideoEditView(SuperUserRequiredMixin, generic.UpdateView):model = Videoform_class = VideoEditFormtemplate_name = 'myadmin/video_edit.html'def get_context_data(self, **kwargs):context = super(VideoEditView, self).get_context_data(**kwargs)clf_list = Classification.objects.all().values()clf_data = {'clf_list':clf_list}context.update(clf_data)return contextdef get_success_url(self):messages.success(self.request, "保存成功")return reverse('myadmin:video_edit', kwargs={'pk': self.kwargs['pk']})

其实编辑页面和发布页面很相似,都是继承UpdateView视图类,并在get_context_data()里面传递分类信息。最终成功后通过messages.success(self.request, "保存成功")消息告之前端。

视频删除

删除功能就更加简单了。路由是

path('video_delete/', views.video_delete, name='video_delete'),

这里通过video_delete函数来实现,前端通过ajax(ajax代码位于static/js/myadmin/video_list.js)调用这个函数。

@ajax_required
@require_http_methods(["POST"])
def video_delete(request): video_id = request.POST['video_id']instance = Video.objects.get(id=video_id)instance.delete()return JsonResponse({"code": 0, "msg": "success"})

获取该视频,然后instance.delete()删除之。

视频分类

分类管理功能包括分类的增删改查。

增删改查的路由是

path('classification_add/', views.ClassificationAddView.as_view(), name='classification_add'),
path('classification_list/', views.ClassificationListView.as_view(), name='classification_list'),
path('classification_edit/<int:pk>/', views.ClassificationEditView.as_view(), name='classification_edit'),
path('classification_delete/', views.classification_delete, name='classification_delete'),

先来看分类添加的功能

分类添加是通过ClassificationAddView视图类来实现的,代码如下

class ClassificationAddView(SuperUserRequiredMixin, generic.View):def get(self, request):form = ClassificationAddForm()return render(self.request, 'myadmin/classification_add.html', {'form': form})def post(self, request):form = ClassificationAddForm(data=request.POST)if form.is_valid():form.save(commit=True)return render(self.request, 'myadmin/classification_add_success.html')return render(self.request, 'myadmin/classification_add.html', {'form': form})

此处是通过get和post一同来实现的,get()负责展示界面,post()负责逻辑判断。在post()中,直接调用form.save来保存记录,然后跳转到成功页myadmin/classification_add_success.html。

分类添加

添加成功

然后点击视频列表,即可查看列表,视频列表的视图类是ClassificationListView,即

class ClassificationListView(AdminUserRequiredMixin, generic.ListView):model = Classificationtemplate_name = 'myadmin/classification_list.html'context_object_name = 'classification_list'paginate_by = 10q = ''def get_context_data(self, *, object_list=None, **kwargs):context = super(ClassificationListView, self).get_context_data(**kwargs)paginator = context.get('paginator')page = context.get('page_obj')page_list = get_page_list(paginator, page)context['page_list'] = page_listcontext['q'] = self.qreturn contextdef get_queryset(self):self.q = self.request.GET.get("q", "")return Classification.objects.filter(title__contains=self.q)

继承ListView来显示列表,通过get_queryset()来实现搜索功能,通过get_context_data()来实现分页功能,通过template_name来指定模板

效果如下

接着来实现编辑和删除功能。

编辑对应的视图类是ClassificationEditView,它的实现超级简单,继承UpdateView即可。

class ClassificationEditView(SuperUserRequiredMixin, generic.UpdateView):model = Classificationform_class = ClassificationEditFormtemplate_name = 'myadmin/classification_edit.html'def get_success_url(self):messages.success(self.request, "保存成功")return reverse('myadmin:classification_edit', kwargs={'pk': self.kwargs['pk']})

编辑页面和添加页面很相似,这里就不贴图了。

最后是删除功能,是通过ajax来实现的,ajax代码位于static/js/myadmin/classification_list.js,在ajax中,通过调用删除接口classification_delete来实现删除功能,

接口classification_delete的代码:

@ajax_required
@require_http_methods(["POST"])
def classification_delete(request):classification_id = request.POST['classification_id']instance = Classification.objects.get(id=classification_id)instance.delete()return JsonResponse({"code": 0, "msg": "success"})

功能略多,同学们可根据自身情况,根据后台demo地址的演示来一步步学习。

基于django的视频点播网站开发-step9-后台视频管理功能相关推荐

  1. 基于django的视频点播网站开发-step11-后台用户管理功能...

    用户管理功能,包含用户添加.列表展示.编辑.删除四大功能.下面我们一一揭晓. 用户添加 我们先实现用户添加功能,我们现在urls.py下添加相关的路由 path('user_add/', views. ...

  2. 基于django的视频点播网站开发-step10-后台评论管理功能...

    本讲中,我们会讲到评论管理功能,数据库中的每一条是来自用户的评价,因此后台中的评论管理只有评论列表和评论删除功能,没有增加评论和编辑评论. 照例我们先添加评论管理的相关路由 path('comment ...

  3. 基于django的视频点播网站开发-step12-后台订阅功能

    本讲我们会讲到一些关于发邮件的技术.我们知道,订阅功能是一个很常见的功能,当用户订阅某个网站后,网站会通过后台给用户发送网站最新的一些动向,一般是通过邮件来发送的.当你阅读完本节内容,会对发邮件的流程 ...

  4. 基于django的视频点播网站开发-step12-后台订阅功能...

    本讲我们会讲到一些关于发邮件的技术.我们知道,订阅功能是一个很常见的功能,当用户订阅某个网站后,网站会通过后台给用户发送网站最新的一些动向,一般是通过邮件来发送的.当你阅读完本节内容,会对发邮件的流程 ...

  5. 基于django的视频点播网站开发-step2-搭建环境

    本讲中,带领大家搭建开发环境.我们会依次安装python.pip.django.mysql和其他的一些必要类库. 安装python 安装 Python 非常简单,去 Python 官方网站 找到 Py ...

  6. 基于python的电商网站建设_基于Django的电子商务网站开发

    Python的安装 目前市场上Python 2.X系列与Python 3.X系列共存的现象.读者可以安装Python 2.X系列或者Python 3.X系列.如果开发的目的是基于原有Python 2. ...

  7. 基于Django手机销售网站

    1,项目功能: (1)商品分类:该模块中,用户可以根据商品的分类信息进行商品检索. (2)商品预览:该模块主要实现商品的详细信息浏览功能. (3)购物车:用户可以把自己喜欢的商品添加到购物车中. (4 ...

  8. php动态网站开发论文,浅谈《基于PHP的动态网站开发》课程的项目案例设计

    电子论文 浅谈<基于PHP的动态网站开发>课程的项目案例设计 时间:2020年05月25日 所属分类:电子论文 点击次数: [摘要]在教学资源建设中,案例设计建设是非常重要的资源之一.运用 ...

  9. springmvc web网站开发上传视频到远程服务器解决方案

    springmvc web网站开发上传视频到远程服务器解决方案!近期在给学校做官方网站设计时,有一个业务需求是,后台要增加一个视频管理模块,管理员在后台可以把本地硬盘剪辑好的视频文件,上传到远程服务器 ...

  10. [django项目] 后台菜单管理功能

    后台菜单管理功能 菜单的管理功能其实就是, 对菜单的增删改查 I. 业务功能分析 1>业务需求分析 后台首页菜单根据用户权限动态生成,不同菜单对应不同的功能视图. 菜单的增删改查. 2>功 ...

最新文章

  1. imx6 LCD 参数配置(lvds为例)
  2. 一日千里 云计算普及势不可挡
  3. 【深度学习的数学】“2×4×1层带sigmoid激活函数的神经网络感知机对三角形平面的分类训练预测”,输出层加偏置b(实时绘制损失函数曲线)(对输入数据归一化)(奇迹出现了!)
  4. java8 streams_Java SE 8新功能介绍:使用Streams API处理集合
  5. activiti 工作流设置并行审批_activity、jbpm5、snakerflow常用工作流审批流对比
  6. printf打印结构体_工程师:这道题80%初学者都没做对!你确定搞懂结构体内存对齐了?...
  7. 多元线性回归的缺陷_轻松阅 | 多元线性回归的“参差不齐
  8. 3个方法解决百度网盘限速 (2018-07-20)
  9. 想要做音乐玩音乐,有这一个软件就够了!
  10. cups 2.4.1编译办法
  11. 从职高到杭电、浙大、MIT计算机博士!
  12. OpenHarmony学习笔记——南向开发环境搭建
  13. Webdriver 爬取新浪滚动新闻
  14. win10打开谷歌浏览器chrome,并进入kiosk模式
  15. 小程序学习笔记01 - 图片识别
  16. 计算机不显示磁盘阵列,识别不到硬盘?bios中怎么改raid为ahci硬盘模式。
  17. jsp2022326税务税收协同办公系统
  18. HTML标签学习基础新人笔记
  19. (附源码)计算机毕业设计ssm党史知识竞赛系统
  20. Java和C++基本类型与语法的区别

热门文章

  1. 数据结构37:线索二叉树的创建
  2. 当Ext.js中xtype: 'checkboxfield'时,没勾选则向后台发送的数据没有字段的解决方法...
  3. [已解决]Tomcat启动报 java.net.BindException: Address already in use: JVM_Bind
  4. 我在开发中所遇到的iOS7新特性以及iOS7与iOS6的适配问题总结
  5. Storm-源码分析-Streaming Grouping (backtype.storm.daemon.executor)
  6. JAVA学习笔记-反射
  7. Kazrog AmpCraft 1992 for Mac - 放大器建模插件
  8. Mac基础知识:Mac日历如何添加提醒事件的教程
  9. 消除代码中的 if-else/switch-case
  10. Debian 8 Jessie desktop on arm