写在前面
本篇笔记我们将介绍课程相关页面的配置,具体包括课程章节信息,章节视频信息,课程评论页面,相关课程推荐,课程播放页面等功能,下面我们依次介绍一下。
本篇笔记对应于第二十篇代码,对应于github的位置是https://github.com/licheetools/eduline。
课程章节信息配置
老规矩,把前端资料里面的course-video.html和course-comment.html页面拷贝到我们的templates文件夹里面,接着修改course-video.html页面,保留部分信息,其余删除,{% block content %} <div id="main">{% endblock %}
里面 <div id="main">是原来course-video.html保留下来的一部分:
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}公开课视频信息 - 慕海学习网{% endblock %}
{% block custom_bread %}
<section>
<div class="wp">
<ul class="crumbs">
<li><a href="{% url 'index' %}">首页</a>></li>
<li><a href="{% url 'course:course_list' %}">公开课程</a>></li>
<li><a href="{% url 'course:course_detail' course.id %}">课程详情</a>></li>
<li>章节信息</li>
</ul>
</div>
</section>
{% endblock %}
{% block custom_css %}
<link rel="stylesheet" type="text/css" href="{% static 'css/muke/base.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'css/muke/common-less.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'css/muke/course/learn-less.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'css/aui.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'css/mooc.css' %}"/>
<link rel="stylesheet" type="text/css" href="{% static 'css/muke/course/common-less.css' %}"/>
{% endblock %}
{% block content %}
<div id="main">
{% endblock %}
就是这个样子(这里面的静态文件路径和url的跳转我都做好了,你按照图示进行修改即可):
然后打开course/urls.py文件,新增以下信息:
from .views import CourseInfoView
# 课程章节信息页url
re_path('info/(?P<course_id>.*)/', CourseInfoView.as_view(), name="course_info"),
接着打开course/views.py文件,新增以下信息:
# 课程章节信息
class CourseInfoView(View):
def get(self, request, course_id):
course = Course.objects.get(id=int(course_id))
return render(request, "course-video.html", {
"course": course,
})
现在打开course-detail.html页面,ctrl+F搜索“开始学习”,配置跳转路径:
<div class="buy btn"><a style="color: white" href="{% url 'courses:course_info' course.id %}">开始学习</a></div>
就是这个样子:
然后运行项目,点击课程详情页面的开始学习就进入到课程章节信息页面了:
现在在后台为指定某一门课添加课程章节信息,便于我们后面的测试:
章节视频信息配置
接下来获取课程的章节:打开courses/models.py文件,在Course函数里面,新定义函数def get_course_lesson用于获取课程的章节:
def get_course_lesson(self):
# 获取课程所有章节
return self.lesson_set.all()
在lesson函数里面,新定义函数def get_lesson_video用于获取章节的视频信息:
def get_lesson_video(self):
# 获取章节视频信息
return self.video_set.all()
现在打开course-video.html页面,配置数据的动态显示:
{% for lesson in course.get_course_lesson %}
<div class="chapter chapter-active" >
<h3>
<strong><i class="state-expand"></i>{{ lesson.name }}</strong>
</h3>
<ul class="video">
{% for video in lesson.get_lesson_video %}
<li>
<a target="_blank" href='/video/3662' class="J-media-item studyvideo">{{ video.name }}({{ video.learn_times }})
<i class="study-state"></i>
</a>
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
就是这个样子:
前面说过,你可以选择不定义函数,自己调用它的queryset方法,那么只需修改course-video.html页面,修改如下:
{% for lesson in course.lesson_set.get_queryset%}
<div class="chapter chapter-active" >
<h3>
<strong><i class="state-expand"></i>{{ lesson.name }}</strong>
</h3>
<ul class="video">
{% for video in lesson.video_set.get_queryset %}
<li>
<a target="_blank" href='/video/3662' class="J-media-item studyvideo">{{ video.name }}({{ video.learn_times }})
<i class="study-state"></i>
</a>
</li>
{% endfor %}
</ul>
</div>
{% endfor %}
刷新一下我们的页面:
资源下载功能
第一步,前往xadmin后台为某一门课添加课程资源,第二步打开courses/views.py文件,修改视图函数:
from .models import CourseResource
all_resources = CourseResource.objects.filter(course=course)
return render(request, "course-video.html", {
"all_resources": all_resources,
})
就是这个样子:
现在打开course-video.html页面,配置资源下载的动态显示:
{% for resources in all_resources %}
<li>
<span ><i class="aui-iconfont aui-icon-file"></i> {{ resources.name }}</span>
<a href="{{ MEDIA_URL }}{{ resources.download }}" class="downcode" target="_blank" download="" data-id="274" title="">下载</a>
</li>
{% endfor %}
就是这个样子:
然后刷新页面,发现显示没有问题。
接下在course-video.html页面完成课程信息的修改:
<div class="static-item ">
<span class="meta-value"><strong>{{ course.get_degree_display }}</strong></span>
<span class="meta">难度</span>
<em></em>
</div>
<div class="static-item static-time">
<span class="meta-value"><strong>{{ course.learn_times }}分钟</strong></span>
<span class="meta">时长</span>
<em></em>
</div>
<div class="static-item">
<span class="meta-value"><strong>{{ course.students }}人</strong></span>
<span class="meta">学习人数</span>
<em></em>
</div>
在配置讲师提示的时候,发现讲师和课程之间没有建立外键连接,所以在courses/models.py文件的Course函数,新增讲师字段 :
from organization.models import Teacher
teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE, verbose_name="讲师", null=True, blank=True)
记得数据库的变动需要两部曲:makemigrations和migrate。
然后前往xadmin后台为这门课添加一个讲师。
然后修改course-video.html页面,修改信息成图示:
然后刷新页面,发现显示没有问题。
课程评论页面配置
打开courses/urls.py文件,配置课程评论页面的url
from .views import CourseCommentView
# 课程评论页面url
re_path('comment/(?P<course_id>.*)/', CourseCommentView.as_view(), name="course_comment"),
然后打开courses/views.py文件,新定义课程评论页面函数:
from operation.models import CourseComments
# 课程评论页面
class CourseCommentView(View):
def get(self, request, course_id):
course = Course.objects.get(id=int(course_id))
all_resources = CourseResource.objects.filter(course=course)
all_comments = CourseComments.objects.all()
return render(request, "course-comment.html", {
"course": course,
"all_resources": all_resources,
"all_comments": all_comments,
})
接着打开course-comment.html页面,修改跳转代码:
<li><a class="ui-tabs-active active" id="learnOn" href="{% url 'courses:course_info' course.id %}"><span>章节</span></a></li>
<li><a id="commentOn" class="" href="{% url 'course:course_comment' course.id %}"><span>评论</span></a></li>
然后打开course-comment.html页面,修改课程信息,资料下载,讲师提示等(和前面在video页面配置的一模一样,这里不再介绍):
接下来打开courses/views.py文件,新定义用于用户增加课程评论的函数:
# 用户增加课程评论
class AddCommentView(View):
def post(self, request):
if not request.user.is_authenticated:
# 未登录时页面提示未登录,并跳转到登录页面
return HttpResponse('{"status":"fail", "msg":"用户未登录"}', content_type='application/json')
course_id = request.POST.get("course_id", 0)
comments = request.POST.get("comments", '')
if course_id >0 and comments:
course_comments = CourseComments()
# get方法只能取出一条数据,如果有多条则抛出异常而且没有数据也抛异常
# filter方法可以取一个列表出来(可以遍历的queryset),没有数据返回空的queryset,是不会抛异常的
course = Course.objects.get(id=int(course_id))
course_comments.course = course
course_comments.comment = comments # 前面comment为数据库中定义字段,要保持一致,否则数据存入不数据库
course_comments.user = request.user
course_comments.save()
return HttpResponse('{"status":"success", "msg":"评论成功"}', content_type='application/json')
else:
return HttpResponse('{"status":"fail", "msg":"评论失败"}', content_type='application/json')
现在回到courses/urls.py文件,我们来配置访问的url:
from .views import AddCommentView
# 用户增加课程评论页面url,注意此处为普通的url因为在post中,我们已经有了参数
path('add_comment/', AddCommentView.as_view(), name="add_comment"),
然后打开course-comment.html页面,在页面底部增加js代码:
{% block custom_js %}
<script type="text/javascript">
//添加评论
$('#js-pl-submit').on('click', function(){
var comments = $("#js-pl-textarea").val()
if(comments == ""){
alert("评论不能为空")
return
}
$.ajax({
cache: false,
type: "POST",
url:"{% url 'course:add_comment' %}",
data:{'course_id':{{ course.id }}, 'comments':comments},
async: true,
beforeSend:function(xhr, settings){
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
},
success: function(data) {
if(data.status == 'fail'){
if(data.msg == '用户未登录'){
window.location.href="{% url 'login' %}";
}else{
alert(data.msg)
}
}else if(data.status == 'success'){
window.location.reload();//刷新当前页面.
}
},
});
});
</script>
{% endblock %}
继续在该页面修改如下代码,使页面评论可以动态加载出来:
{% for user_comments in all_comments %}
<li class="post-row">
<div class="media">
<span target="_blank"><img src='{{ MEDIA_URL }}{{ user_comments.user.image }}' width='40' height='40' /></span>
</div>
<div class="bd">
<div class="tit">
<span target="_blank">{{ user_comments.user.username }}</span>
</div>
<p class="cnt">{{ user_comments.user.comment }}</p>
<div class="footer clearfix">
<span title="创建时间" class="l timeago">{{ user_comments.add_time }}</span>
</div>
</div>
</li>
{% endfor %}
然后你可以在图示位置打上断点,开启debug模式:
发现没有问题,我们可以去掉断点,自己再增加一条,页面是不是已经自动更新了你的评论内容。
相关课程推荐配置
打开courses/views.py文件,找到CourseInfoView这个函数,修改为如下:
# 课程章节信息
class CourseInfoView(View):
def get(self, request, course_id):
course = Course.objects.get(id=int(course_id))
all_resources = CourseResource.objects.filter(course=course)
# 取出所有选过这门课的学生
user_courses = UserCourse.objects.filter(course=course)
# 取出所有选过这门课的学生的id,采用递归表达式形式
user_ids = [user_course.user.id for user_course in user_courses]
# 取出刚才那些学生选过的所有的课程
all_user_courses = UserCourse.objects.filter(user_id__in=user_ids)
# 取出刚才那些学生选过的所有的课程的id,同样采用递归表达式形式
course_ids = [all_user_course.course_id for all_user_course in all_user_courses]
# 取出学过该课程用户学过的其他课程
relate_courses = Course.objects.filter(id__in=course_ids).order_by("-click_nums")[:5]
return render(request, "course-video.html", {
"course": course,
"all_resources": all_resources,
"relate_courses": relate_courses,
})
注意:双下划线代表代表传进来的是一个可以遍历的list。
接着就是在前端页面配置动态加载信息了(记得course-video.html和course_comment.html这两个页面都需要配置,一模一样):
<ul class="other-list">
{% for relate_course in relate_courses %}
<li class="curr">
<a href="{% url 'course:course_detail' relate_course.id %}" target="_blank">
<img src="{{ MEDIA_URL }}{{ relate_course.image }}"
alt="{{ relate_course.name }}">
<span class="name autowrap">{{ relate_course.name }}</span>
</a>
</li>
{% endfor %}
</ul>
就是这个样子:
然后刷新一下我们的页面,发现没有问题!
不过还有一个问题,那就是用户如果没有登录,那是不能让他进入课程章节这个页面的,因此需要判断一下。这里因为使用的是方法型编程所以可以使用装饰器loginrequired来进行判断。
在utils文件夹下面,新建一个名为mixin_utils.py文件,在里面添加如下代码:
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
class LoginRequiredMixin(object):
@method_decorator(login_required(login_url='/login/'))
def dispatch(self, request, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
接着打开courses/views.py文件,在里面修改CourseInfoView和CourseCommentView,修改后如下:
from utils.mixin_utils import LoginRequiredMixin
# 课程章节信息
class CourseInfoView(LoginRequiredMixin, View):
login_url = '/login/'
redirect_field_name = 'redirect_to'
def get(self, request, course_id):
course = Course.objects.get(id=int(course_id))
all_resources = CourseResource.objects.filter(course=course)
# 查询用户是否已经开始学习了该课程,如果没有则开始学习
user_courses = UserCourse.objects.filter(user=request.user, course=course)
if not user_courses:
user_course = UserCourse(user=request.user, course=course)
course.students += 1
course.save()
user_course.save()
# 取出所有选过这门课的学生
user_courses = UserCourse.objects.filter(course=course)
# 取出所有选过这门课的学生的id,采用递归表达式形式
user_ids = [user_course.user.id for user_course in user_courses]
# 取出刚才那些学生选过的所有的课程
all_user_courses = UserCourse.objects.filter(user_id__in=user_ids)
# 取出刚才那些学生选过的所有的课程的id,同样采用递归表达式形式
course_ids = [all_user_course.course_id for all_user_course in all_user_courses]
# 取出学过该课程用户学过的其他课程
relate_courses = Course.objects.filter(id__in=course_ids).order_by("-click_nums")[:5]
return render(request, "course-video.html", {
"course": course,
"all_resources": all_resources,
"relate_courses": relate_courses,
})
# 课程评论页面
class CourseCommentView(LoginRequiredMixin, View):
login_url = '/login/'
redirect_field_name = 'redirect_to'
def get(self, request, course_id):
course = Course.objects.get(id=int(course_id))
all_resources = CourseResource.objects.filter(course=course)
all_comments = CourseComments.objects.all()
return render(request, "course-comment.html", {
"course": course,
"all_resources": all_resources,
"all_comments": all_comments,
})
刷新一下页面,点几个课程试试看,发现都在该同学还学过哪些课里推荐了。
课程播放页面配置
老规矩,把前端资料里面的course-play.html拷贝到我们的templates文件夹里面,然后替换继承base页面,这里就不细说了,直接贴图:
打开courses/urls.py文件,新增代码:
from .views import VideoPlayView
# 视频播放页面url
re_path('video/(?P<video_id>.*)/', VideoPlayView.as_view(), name="video_play"),
或者 re_path('video/(?P<video_id>\d+)/', VideoPlayView.as_view(), name="video_play"),都是可以的
接着打开courses/views.py文件,新增代码:
from .models import Video
# 视频播放页面
class VideoPlayView(LoginRequiredMixin, View):
login_url = '/login/'
redirect_field_name = 'redirect_to'
def get(self, request, video_id):
video = Video.objects.get(id=int(video_id))
course = video.lesson.course
all_resources = CourseResource.objects.filter(course=course)
# 查询用户是否已经开始学习了该课程,如果没有则开始学习
user_courses = UserCourse.objects.filter(user=request.user, course=course)
if not user_courses:
user_course = UserCourse(user=request.user, course=course)
course.students += 1
course.save()
user_course.save()
# 取出所有选过这门课的学生
user_courses = UserCourse.objects.filter(course=course)
# 取出所有选过这门课的学生的id,采用递归表达式形式
user_ids = [user_course.user.id for user_course in user_courses]
# 取出刚才那些学生选过的所有的课程
all_user_courses = UserCourse.objects.filter(user_id__in=user_ids)
# 取出刚才那些学生选过的所有的课程的id,同样采用递归表达式形式
course_ids = [all_user_course.course_id for all_user_course in all_user_courses]
# 取出学过该课程用户学过的其他课程
relate_courses = Course.objects.filter(id__in=course_ids).order_by("-click_nums")[:5]
return render(request, "course-play.html", {
"course": course,
"all_resources": all_resources,
"relate_courses": relate_courses,
"video": video,
})
上面的代码和之前在课程章节信息里面定义的几乎一模一样,只是course的来源不一样。
接着打开course-video.html文件,配置跳转链接:
{% for video in lesson.get_lesson_video %}
<li>
<a target="_blank" href='{% url 'course:video_play' video.id %}'
class="J-media-item studyvideo">{{ video.name }}({{ video.learn_times }})
<i class="study-state"></i>
</a>
</li>
{% endfor %}
然后打开course-video.html文件,配置视频链接,记住由于我们这边是type='video/mp4'所以后台所添加的视频必须是.mp4结尾,否则会出错。
刷新一下,发现页面跳转没有问题,显示也没有问题。
大家可以把自己的视频上传到七牛云,然后把生成的外键添加到后台即可,这里不详细介绍,直接开启传送大门:七牛云存储如何上传视频文件
至此,本篇关于课程相关页面的配置介绍就到此结束,感谢你的赏阅。
本篇笔记对应于第二十篇代码,对应于github的位置是https://github.com/licheetools/eduline。
网友评论