前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >零基础使用Django2.0.1打造在线教育网站(二十):课程相关页面配置

零基础使用Django2.0.1打造在线教育网站(二十):课程相关页面配置

原创
作者头像
啃饼思录
修改2018-09-10 21:44:22
8990
修改2018-09-10 21:44:22
举报

关于博主

努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

代码语言:txt
复制
                 微信公众号:  啃饼思录
代码语言:txt
复制
                 QQ: 2810706745(啃饼小白)

写在前面

本篇笔记我们将介绍课程相关页面的配置,具体包括课程章节信息,章节视频信息,课程评论页面,相关课程推荐,课程播放页面等功能,下面我们依次介绍一下。

本篇笔记对应于第二十篇代码,对应于github的位置是https://github.com/licheetools/eduline

课程章节信息配置

老规矩,把前端资料里面的course-video.htmlcourse-comment.html页面拷贝到我们的templates文件夹里面,接着修改course-video.html页面,保留部分信息,其余删除,{% block content %} <div id="main">{% endblock %}里面 <div id="main">是原来course-video.html保留下来的一部分:

代码语言:txt
复制
{% 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文件,新增以下信息:

代码语言:txt
复制
from .views import CourseInfoView

# 课程章节信息页url
    re_path('info/(?P<course_id>.*)/', CourseInfoView.as_view(), name="course_info"),

接着打开course/views.py文件,新增以下信息:

代码语言:txt
复制
# 课程章节信息
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搜索“开始学习”,配置跳转路径:

代码语言:txt
复制
<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用于获取课程的章节:

代码语言:txt
复制
    def get_course_lesson(self):
        # 获取课程所有章节
        return self.lesson_set.all()

在lesson函数里面,新定义函数def get_lesson_video用于获取章节的视频信息:

代码语言:txt
复制
    def get_lesson_video(self):
        # 获取章节视频信息
        return self.video_set.all()

现在打开course-video.html页面,配置数据的动态显示:

代码语言:txt
复制
{% 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页面,修改如下:

代码语言:txt
复制
{% 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文件,修改视图函数:

代码语言:txt
复制
from .models import  CourseResource

all_resources = CourseResource.objects.filter(course=course)
return render(request, "course-video.html", {
            "all_resources": all_resources,
        })
就是这个样子:

现在打开course-video.html页面,配置资源下载的动态显示:

代码语言:txt
复制
{% for resources in all_resources %}
                               <li>
                                <span ><i class="aui-iconfont aui-icon-file"></i>&nbsp;&nbsp;{{ resources.name }}</span>
                                <a href="{{ MEDIA_URL }}{{ resources.download }}" class="downcode" target="_blank" download="" data-id="274" title="">下载</a>
                            </li>
                           {% endfor %}
就是这个样子:

然后刷新页面,发现显示没有问题。

接下在course-video.html页面完成课程信息的修改:

代码语言:txt
复制
<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函数,新增讲师字段 :

代码语言:txt
复制
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

代码语言:txt
复制
from .views import CourseCommentView

 # 课程评论页面url
    re_path('comment/(?P<course_id>.*)/', CourseCommentView.as_view(), name="course_comment"),

然后打开courses/views.py文件,新定义课程评论页面函数:

代码语言:txt
复制
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页面,修改跳转代码:

代码语言:txt
复制
<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文件,新定义用于用户增加课程评论的函数:

代码语言:txt
复制
# 用户增加课程评论
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:

代码语言:txt
复制
from .views import  AddCommentView

    # 用户增加课程评论页面url,注意此处为普通的url因为在post中,我们已经有了参数
    path('add_comment/', AddCommentView.as_view(), name="add_comment"),

然后打开course-comment.html页面,在页面底部增加js代码:

代码语言:txt
复制
{% 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 %}

继续在该页面修改如下代码,使页面评论可以动态加载出来:

代码语言:txt
复制
{% 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这个函数,修改为如下:

代码语言:txt
复制
# 课程章节信息
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这两个页面都需要配置,一模一样):

代码语言:txt
复制
 <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文件,在里面添加如下代码:

代码语言:txt
复制
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,修改后如下:

代码语言:txt
复制
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文件,新增代码:

代码语言:txt
复制
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文件,新增代码:

代码语言:txt
复制
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文件,配置跳转链接:

代码语言:txt
复制
{% 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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于博主
  • 写在前面
  • 课程章节信息配置
  • 章节视频信息配置
    • 资源下载功能
    • 课程评论页面配置
    • 相关课程推荐配置
    • 课程播放页面配置
    相关产品与服务
    对象存储
    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档