美文网首页django零基础使用Django2.0.1打造在线教育网站
零基础使用Django2.0.1打造在线教育网站(二十):课程相

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

作者: 啃饼小白 | 来源:发表于2018-08-14 10:22 被阅读15次

    写在前面

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

    本篇笔记对应于第二十篇代码,对应于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保留下来的一部分:

    {% 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>&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页面完成课程信息的修改:
    <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

    相关文章

      网友评论

        本文标题:零基础使用Django2.0.1打造在线教育网站(二十):课程相

        本文链接:https://www.haomeiwen.com/subject/alkdbftx.html