基于django的视频点播网站开发-step9-后台视频管理功能
从本讲开始,我们开始视频管理功能的开发,视频管理包括视频上传、视频列表、视频编辑、视频删除。另外还有视频分类的功能,会一同讲解。这一讲非常重要,因为你将学习到一些之前没有学过的技术,比如大文件上传技术。
视频上传
我们先来实现视频的上传,视频的上传采用的是分块上传的策略,并用了分块上传类库: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 kB formData: form_data, add: function(e, data) { // Called before starting upload var 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 kB data.submit(); $('#progress_label').on('click', false); $('#progress_layout').show() }, chunkdone: function (e, data) { // Called after uploading each chunk if (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 = MyChunkedUpload def 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 = Video form_class = VideoPublishForm template_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 context def 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 = Video template_name = 'myadmin/video_list.html' context_object_name = 'video_list' paginate_by = 10 q = '' 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_list context['q'] = self.q return context def 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 = Video form_class = VideoEditForm template_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 context def 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 = Classification template_name = 'myadmin/classification_list.html' context_object_name = 'classification_list' paginate_by = 10 q = '' 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_list context['q'] = self.q return context def 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 = Classification form_class = ClassificationEditForm template_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地址的演示来一步步学习。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
基于django的视频点播网站开发-step8-后台登录功能
从本讲起,我们会介绍后台管理系统的开发,后台管理,主要是对数据库中的数据进行增、删、改、查的操作,满足网站管理员对网站的管理与维护的需求。 其实,django自带的也有一个后台管理系统(/admin),但是自带的后台非常简陋,无论是界面,还是功能上,都无法满足用户的需求,因此,我们自己开发了一套后台管理系统。 demo地址 测试账号: admin123 密码: admin123 后台管理属于一个单独的模块,我们创建一个新的应用,命名为myadmin python3 manage.py startapp myadmin 好,之后的功能都是基于myadmin来实现的。 因为前面我们已经创建了user模块,所以此处的登录功能是基于之前的user模块来实现的。 首先在myadmin/urls.py中添加登录和登出的路由 from django.urls import path from . import views app_name = 'myadmin' urlpatterns = [ path('login/', views.login, name='login'), path('logo...
- 下一篇
基于django的视频点播网站开发-step10-后台评论管理功能
本讲中,我们会讲到评论管理功能,数据库中的每一条是来自用户的评价,因此后台中的评论管理只有评论列表和评论删除功能,没有增加评论和编辑评论。 照例我们先添加评论管理的相关路由 path('comment_list/', views.CommentListView.as_view(), name='comment_list'), path('comment_delete/', views.comment_delete, name='comment_delete'), 首先是评论列表的展示,我们通过CommentListView视图类来实现,该类依然是继承ListView来实现的。代码如下 class CommentListView(AdminUserRequiredMixin, generic.ListView): model = Comment template_name = 'myadmin/comment_list.html' context_object_name = 'comment_list' paginate_by = 10 q = '' def get_context_da...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Windows10,CentOS7,CentOS8安装Nodejs环境
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8安装Docker,最新的服务器搭配容器使用
- 设置Eclipse缩进为4个空格,增强代码规范