zoukankan      html  css  js  c++  java
  • (项目)在线教育平台(九)

    十一、课程章节功能

    1、前端页面配置

      将课程章节页面course-video.html拷贝到templates目录下。

      继承base.html页面,重写需要block的地方:

    2、课程章节接口

    1 class CourseLessonView(View):
    2     """课程章节"""
    3     def get(self, request, course_id):
    4         # 根据前端传递的课程id找到对应的课程
    5         course = Course.objects.get(id=int(course_id))
    6 
    7         return render(request, 'course-video.html', {
    8             'course': course
    9         })

      配置url:

    1 from .views import CourseLessonView
    2 
    3 urlpatterns = [
    4     re_path('lesson/(?P<course_id>d+)/', CourseLessonView.as_view(), name='course_lesson'),  # 课程章节
    5 ]

      然后在课程详情页面修改点击开始学习后进入课程章节页面的url:

      修改课程章节页面面包屑中的url跳转:

      在章节中有视频信息,需要给视频信息添加一个访问地址字段,在视频的model中添加视频访问地址的字段:

     1 class Video(models.Model):
     2     """视频"""
     3     lesson = models.ForeignKey(Lesson, verbose_name='章节', on_delete=models.CASCADE)
     4     name = models.CharField('视频名', max_length=100)
     5     url = models.CharField('访问地址', default='', max_length=200)
     6     add_time = models.DateTimeField('添加时间', default=datetime.now)
     7 
     8     class Meta:
     9         verbose_name = '视频'
    10         verbose_name_plural = verbose_name

      迁移数据库。

      然后在后台中添加章节和视频的数据。

       在课程章节页面需要有课程的所有章节、以及视频,所以需要在课程的model中获取所有的章节和章节的model中获取所有的视频以及视频的model中添加一个学习时长字段:

     1 class Course(models.Model):
     2     """课程"""
     3     DEGREE_CHOICES = (
     4         ('cj', '初级'),
     5         ('zj', '中级'),
     6         ('gj', '高级')
     7     )
     8 
     9     name = models.CharField('课程名', max_length=50)
    10     desc = models.CharField('课程描述', max_length=300)
    11     detail = models.TextField('课程详情')
    12     degree = models.CharField('课程难度', choices=DEGREE_CHOICES, max_length=2)
    13     learn_times = models.IntegerField('学习时长(分钟数)', default=0)
    14     students = models.IntegerField('学习人数', default=0)
    15     fav_nums = models.IntegerField('收藏人数', default=0)
    16     click_nums = models.IntegerField('点击数', default=0)
    17     image = models.ImageField('封面图', upload_to='courses/%Y/%m', max_length=100)
    18     course_org = models.ForeignKey(CourseOrg, verbose_name='所属机构', on_delete=models.CASCADE, null=True, blank=True)
    19     category = models.CharField('课程类别', max_length=20, default='')
    20     tag = models.CharField('标签', max_length=10, default='')
    21     add_time = models.DateTimeField('添加时间', default=datetime.now)
    22 
    23     class Meta:
    24         verbose_name = '课程'
    25         verbose_name_plural = verbose_name
    26 
    27     # 获取章节数
    28     def get_zj_nums(self):
    29         return self.lesson_set.all().count()
    30 
    31     # 获取学习用户
    32     def get_learn_users(self):
    33         return self.usercourse_set.all()[:5]
    34 
    35     # 获取章节
    36     def get_course_lesson(self):
    37         return self.lesson_set.all()
    38 
    39     def __str__(self):
    40         return self.name
    41 
    42 
    43 class Lesson(models.Model):
    44     """章节"""
    45     course = models.ForeignKey(Course, verbose_name='课程', on_delete=models.CASCADE)
    46     name = models.CharField('章节名', max_length=100)
    47     add_time = models.DateTimeField('添加时间', default=datetime.now)
    48 
    49     class Meta:
    50         verbose_name = '章节'
    51         verbose_name_plural = verbose_name
    52 
    53     # 获取所有的视频
    54     def get_lesson_video(self):
    55         return self.video_set.all()
    56 
    57     def __str__(self):
    58         return '《{}》课程的章节:{}'.format(self.course.name, self.name)
    59 
    60 
    61 class Video(models.Model):
    62     """视频"""
    63     lesson = models.ForeignKey(Lesson, verbose_name='章节', on_delete=models.CASCADE)
    64     name = models.CharField('视频名', max_length=100)
    65     url = models.CharField('访问地址', default='', max_length=200)
    66     learn_times = models.IntegerField('学习时长(分钟数)', default=0)
    67     add_time = models.DateTimeField('添加时间', default=datetime.now)
    68 
    69     class Meta:
    70         verbose_name = '视频'
    71         verbose_name_plural = verbose_name
    View Code

      然后迁移数据库。

      修改课程章节页面中显示课程章节及视频的代码:

      刷新之后即可看到后台添加的视频章节及视频信息。

      在课程章节页面右侧有资源下载,首先在后台添加资源文件,然后完善课程章节接口获取资源文件的逻辑:

     1 class CourseLessonView(View):
     2     """课程章节"""
     3     def get(self, request, course_id):
     4         # 根据前端传递的课程id找到对应的课程
     5         course = Course.objects.get(id=int(course_id))
     6 
     7         # 获取所有的资源文件
     8         all_resources = CourseResourse.objects.filter(course=course)
     9 
    10         return render(request, 'course-video.html', {
    11             'course': course,
    12             'all_resources': all_resources
    13         })

      修改课程章节页面中显示资源下载的代码:

      然后修改章节上面显示课程信息的相关代码:

      在资源下载下面有讲师提示,需要在课程的model中添加教师的外键,还有课程须知以及老师告诉你的两个字段:

     1 class Course(models.Model):
     2     """课程"""
     3     DEGREE_CHOICES = (
     4         ('cj', '初级'),
     5         ('zj', '中级'),
     6         ('gj', '高级')
     7     )
     8 
     9     name = models.CharField('课程名', max_length=50)
    10     desc = models.CharField('课程描述', max_length=300)
    11     detail = models.TextField('课程详情')
    12     degree = models.CharField('课程难度', choices=DEGREE_CHOICES, max_length=2)
    13     learn_times = models.IntegerField('学习时长(分钟数)', default=0)
    14     students = models.IntegerField('学习人数', default=0)
    15     fav_nums = models.IntegerField('收藏人数', default=0)
    16     click_nums = models.IntegerField('点击数', default=0)
    17     image = models.ImageField('封面图', upload_to='courses/%Y/%m', max_length=100)
    18     course_org = models.ForeignKey(CourseOrg, verbose_name='所属机构', on_delete=models.CASCADE, null=True, blank=True)
    19     category = models.CharField('课程类别', max_length=20, default='')
    20     tag = models.CharField('标签', max_length=10, default='')
    21     teacher = models.ForeignKey(Teacher, verbose_name='机构讲师', on_delete=models.CASCADE, null=True, blank=True)
    22     courseneed_know = models.CharField('课程须知', max_length=300, default='')
    23     teacher_tellyou = models.CharField('老师告诉你', max_length=300, default='')
    24     add_time = models.DateTimeField('添加时间', default=datetime.now)
    25 
    26     class Meta:
    27         verbose_name = '课程'
    28         verbose_name_plural = verbose_name
    29 
    30     # 获取章节数
    31     def get_zj_nums(self):
    32         return self.lesson_set.all().count()
    33 
    34     # 获取学习用户
    35     def get_learn_users(self):
    36         return self.usercourse_set.all()[:5]
    37 
    38     # 获取章节
    39     def get_course_lesson(self):
    40         return self.lesson_set.all()
    41 
    42     def __str__(self):
    43         return self.name

      迁移数据库,然后在后台的课程中添加讲师,修改课程章节页面中显示讲师提示的代码:

    3、相关课程推荐

      在课程章节页面的右侧最下方有相关课程的推荐,首先在课程章节接口中添加相关课程推荐的逻辑:

     1 class CourseLessonView(View):
     2     """课程章节"""
     3     def get(self, request, course_id):
     4         # 根据前端传递的课程id找到对应的课程
     5         course = Course.objects.get(id=int(course_id))
     6 
     7         # 获取所有的资源文件
     8         all_resources = CourseResourse.objects.filter(course=course)
     9 
    10         # 相关课程推荐
    11         # 找到学习这门课程的所有用户
    12         user_courses = UserCourse.objects.filter(course=course)
    13         # 找到学习这门课的所有用户的id
    14         user_ids = [user_course.user_id for user_course in user_courses]
    15         # 通过所有用户的id,找到所有用户学习过的所有课程
    16         all_user_courses = UserCourse.objects.filter(user_id__in=user_ids)
    17         # 取出所有课程id
    18         course_ids = [all_user_course.course_id for all_user_course in all_user_courses]
    19         # 通过所有课程id找到所有的课程,按点击量区5个
    20         relate_courses = Course.objects.filter(id__in=course_ids).order_by('-click_nums')[:5]
    21 
    22 
    23         return render(request, 'course-video.html', {
    24             'course': course,
    25             'all_resources': all_resources,
    26             'relate_courses': relate_courses
    27         })

      然后修改课程章节页面中显示相关课程推荐的代码:

     十二、课程评论功能

    1、前端页面配置

      将课程评论页面course-comment.html拷贝到templates目录下。

      继承base.html页面,重写需要block的地方:

    2、课程评论接口

     1 class CourseCommentsView(View):
     2     """课程评论"""
     3     def get(self, request, course_id):
     4         course = Course.objects.get(id=int(course_id))
     5         all_resources = CourseResourse.objects.filter(course=course)
     6 
     7         # 获取所有的评论信息
     8         all_comments = CourseComments.objects.all()
     9 
    10         return render(request, 'course-comment.html', {
    11             'course': course,
    12             'all_resources': all_resources,
    13             'all_comments': all_comments
    14         })

      配置url:

    1 from .views import CourseCommentsView
    2 
    3 urlpatterns = [
    4     re_path('comment/(?P<course_id>d+)/', CourseCommentsView.as_view(), name='course_comment'),  # 课程评论
    5 ]

      然后修改课程章节页面跳转到课程评论页面的url:

      课程评论页面右侧的课程资源下载和讲师提示的代码和课程章节页面的代码一样,只需要拷贝过来即可。

      添加评论功能需要重新写一个添加评论的接口:

     1 class AddCommentsView(View):
     2     """添加评论"""
     3     def post(self, request):
     4         # 未登录不能评论,返回json数据由前端返回登录页面
     5         if not request.user.is_authenticated:
     6             return HttpResponse('{"status": "fail", "msg": "用户未登录"}', content_type='application/json')
     7 
     8         # 从request中获取课程的id和评论信息
     9         course_id = request.POST.get('course_id', 0)
    10         comments = request.POST.get('comments', '')
    11 
    12         # 将评论信息保存到数据库
    13         if int(course_id)>0 and comments:
    14             course_comments = CourseComments()
    15             course = Course.objects.get(id=int(course_id))
    16             course_comments.course = course
    17             course_comments.comments = comments
    18             course_comments.user = request.user
    19             course_comments.save()
    20 
    21             return HttpResponse('{"status": "success", "msg": "评论成功"}', content_type='application/json')
    22         else:
    23             return HttpResponse('{"status": "fail", "msg": "评论失败"}', content_type='application/json')

      配置url:

    1 from .views import AddCommentsView
    2 
    3 urlpatterns = [
    4     path('add_comment/', AddCommentsView.as_view(), name='add_comment'),  # 添加评论
    5 ]

      评论信息是通过script代码通过ajax异步提交的,需要在课程评论页面的最后加上script代码:

     1 {% block custom_js %}
     2     <script type="text/javascript">
     3     //添加评论
     4     $('#js-pl-submit').on('click', function(){
     5         var comments = $("#js-pl-textarea").val()
     6         if(comments == ""){
     7             alert("评论不能为空")
     8             return
     9         }
    10         $.ajax({
    11             cache: false,
    12             type: "POST",
    13             url:"{% url 'course:add_comment' %}",
    14             data:{'course_id':{{ course.id }}, 'comments':comments},
    15             async: true,
    16             beforeSend:function(xhr, settings){
    17                 xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
    18             },
    19             success: function(data) {
    20                 if(data.status == 'fail'){
    21                     if(data.msg == '用户未登录'){
    22                         window.location.href="/login/";
    23                     }else{
    24                         alert(data.msg)
    25                     }
    26 
    27                 }else if(data.status == 'success'){
    28                     window.location.reload();//刷新当前页面.
    29                 }
    30             },
    31         });
    32     });
    33 
    34 </script>
    35 {% endblock %}

      然后修改课程评论页面中显示评论信息的代码:

      现在就可以提交评论信息了,并且是异步提交,不会刷新页面。

     3、课程与用户相关联

      在课程详情页面点击开始学习之后,应该将课程与用户关联起来。

      如果点击开始学习,需要验证用户是否是登录状态,如果没有登录需要让用户先登录,将验证登录这个功能写成一个类,哪个接口需要验证登录继承这个类即可。在utils目录下创建文件mixin_utils.py(将最基本的类都放在这个文件中):

     1 from django.utils.decorators import method_decorator
     2 from django.contrib.auth.decorators import login_required
     3 
     4 
     5 class LoginRequiredMixin(object):
     6     """验证登录基类"""
     7 
     8     @method_decorator(login_required(login_url='/login/'))
     9     def dispatch(self, request, *args, **kwargs):
    10         return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)

      然后让课程章节接口和课程评论接口都继承这个基类,继承之后,没有登录的用户点击开始学习,会跳转到登录页面:

     1 class CourseLessonView(LoginRequiredMixin, View):
     2     """课程章节"""
     3     def get(self, request, course_id):
     4         # 根据前端传递的课程id找到对应的课程
     5         course = Course.objects.get(id=int(course_id))
     6 
     7         # 获取所有的资源文件
     8         all_resources = CourseResourse.objects.filter(course=course)
     9 
    10         # 相关课程推荐
    11         # 找到学习这门课程的所有用户
    12         user_courses = UserCourse.objects.filter(course=course)
    13         # 找到学习这门课的所有用户的id
    14         user_ids = [user_course.user_id for user_course in user_courses]
    15         # 通过所有用户的id,找到所有用户学习过的所有课程
    16         all_user_courses = UserCourse.objects.filter(user_id__in=user_ids)
    17         # 取出所有课程id
    18         course_ids = [all_user_course.course_id for all_user_course in all_user_courses]
    19         # 通过所有课程id找到所有的课程,按点击量区5个
    20         relate_courses = Course.objects.filter(id__in=course_ids).order_by('-click_nums')[:5]
    21 
    22 
    23         return render(request, 'course-video.html', {
    24             'course': course,
    25             'all_resources': all_resources,
    26             'relate_courses': relate_courses
    27         })
    28 
    29 
    30 class CourseCommentsView(LoginRequiredMixin, View):
    31     """课程评论"""
    32     def get(self, request, course_id):
    33         course = Course.objects.get(id=int(course_id))
    34         all_resources = CourseResourse.objects.filter(course=course)
    35 
    36         # 获取所有的评论信息
    37         all_comments = CourseComments.objects.all()
    38 
    39         return render(request, 'course-comment.html', {
    40             'course': course,
    41             'all_resources': all_resources,
    42             'all_comments': all_comments
    43         })
    View Code

      然后将用户和课程关联起来,完善课程章节接口:

     1 class CourseLessonView(LoginRequiredMixin, View):
     2     """课程章节"""
     3     def get(self, request, course_id):
     4         # 根据前端传递的课程id找到对应的课程
     5         course = Course.objects.get(id=int(course_id))
     6 
     7         # 课程和用户关联,先判断用户是否已经学习过该课程
     8         user_courses = UserCourse.objects.filter(user=request.user, course=course)
     9         if not user_courses:
    10             # 没有学习过该课程,关联
    11             user_course = UserCourse(user=request.user, course=course)
    12             user_course.save()
    13 
    14         # 获取所有的资源文件
    15         all_resources = CourseResourse.objects.filter(course=course)
    16 
    17         # 相关课程推荐
    18         # 找到学习这门课程的所有用户
    19         user_courses = UserCourse.objects.filter(course=course)
    20         # 找到学习这门课的所有用户的id
    21         user_ids = [user_course.user_id for user_course in user_courses]
    22         # 通过所有用户的id,找到所有用户学习过的所有课程
    23         all_user_courses = UserCourse.objects.filter(user_id__in=user_ids)
    24         # 取出所有课程id
    25         course_ids = [all_user_course.course_id for all_user_course in all_user_courses]
    26         # 通过所有课程id找到所有的课程,按点击量区5个
    27         relate_courses = Course.objects.filter(id__in=course_ids).order_by('-click_nums')[:5]
    28 
    29         return render(request, 'course-video.html', {
    30             'course': course,
    31             'all_resources': all_resources,
    32             'relate_courses': relate_courses
    33         })

      现在点击开始学习之后,在页面的右下角就有学过的其他课程了。

    十三、视频播放功能

      视频播放器我们使用video.js,它是一款基于HTML5的网络视频播放器。它支持HTML5和Flash视频,以及YouTube和Vimeo(通过插件)。支持在桌面和移动设备上播放视频。

    1、前端页面配置

      将视频播放页面course-play.html拷贝到templates目录下。

      继承base.html页面,重写需要block的地方:

     

      custom_css中的代码如下:

      然后下载video-js.min.css和video.min.js分别放到css和js目录下。

    2、视频播放接口

     1 class VideoPlayView(LoginRequiredMixin, View):
     2     """视频播放"""
     3     def get(self, request, video_id):
     4         # 根据前端的视频id找到对应的视频
     5         video = Video.objects.get(id=int(video_id))
     6 
     7         # 通过外键先找到章节在找到对应的课程,然后学习人数加1
     8         course = video.lesson.course
     9         course.students += 1
    10         course.save()
    11 
    12         # 查询用户是否已经学习了该课程,如果没有将课程和用户关联
    13         user_courses = UserCourse.objects.filter(user=request.user, course=course)
    14         if not user_courses:
    15             user_course = UserCourse(user=request.user, course=course)
    16             user_course.save()
    17 
    18         # 相关课程推荐
    19         user_courses = UserCourse.objects.filter(course=course)
    20         user_ids = [user_course.user_id for user_course in user_courses]
    21         all_user_courses = UserCourse.objects.filter(user_id__in=user_ids)
    22         course_ids = [all_user_course.course_id for all_user_course in all_user_courses]
    23         relate_courses = Course.objects.filter(id__in=course_ids).order_by('-click_nums')[:5]
    24 
    25         # 获取所有资源文件
    26         all_resources = CourseResourse.objects.filter(course=course)
    27 
    28         return render(request, 'course-play.html', {
    29             'course': course,
    30             'all_resources': all_resources,
    31             'relate_courses': relate_courses,
    32             'video': video
    33         })

      配置url:

    1 from .views import VideoPlayView
    2 
    3 urlpatterns = [
    4     re_path('video/(?P<video_id>d+)/', VideoPlayView.as_view(), name='video_play'),  # 视频播放
    5 ]

      然后修改课程章节页面章节中跳转到视频页面的url:

      最后将视频播放页面中显示代码进行修改:

      1 {% extends 'base.html' %}
      2 
      3 {% load staticfiles %}
      4 
      5 {% block titile %}
      6     {{ video.name }} -- 知能网
      7 {% endblock %}
      8 
      9 {% block custom_bread %}
     10     <section>
     11         <div class="wp">
     12             <div class="crumbs">
     13                 <ul>
     14                     <li><a href="{% url 'index' %}">首页</a>></li>
     15                     <li><a href="{% url 'course:course_list' %}">公开课程</a>></li>
     16                     <li><a href="{% url 'course:course_detail' course.id %}">{{ course.name }}</a>></li>
     17                     <li>{{ video.name }}</li>
     18                 </ul>
     19             </div>
     20         </div>
     21     </section>
     22 {% endblock %}
     23 
     24 {% block custom_css %}
     25     <link rel="stylesheet" type="text/css" href="{% static 'css/video-js.min.css' %}">
     26     <link rel="stylesheet" type="text/css" href="{% static 'css/muke/base.css' %}"/>
     27     <link rel="stylesheet" type="text/css" href="{% static 'css/muke/common-less.css' %}"/>
     28     <link rel="stylesheet" type="text/css" href="{% static 'css/muke/course/learn-less.css' %}"/>
     29     <link rel="stylesheet" type="text/css" href="{% static 'css/mooc.css' %}"/>
     30     <link rel="stylesheet" type="text/css" href="{% static 'css/muke/course/common-less.css' %}">
     31     <style>
     32         .video-js .vjs-big-play-button {
     33             top: 50%;
     34             left: 50%;
     35         }
     36     </style>
     37 {% endblock %}
     38 
     39 {% block custom_js %}
     40     <script src="{% static 'js/video.min.js' %}" type="text/javascript"></script>
     41 {% endblock %}
     42 
     43 {% block content %}
     44     <div id="main">
     45 {#    video.js视频播放器#}
     46         <div style="1200px;height: 650px; margin-left:100px">
     47                 <video id="example_video_1" class="video-js vjs-default-skin" controls preload="none" width="1200"
     48                        poster="http://video-js.zencoder.com/oceans-clip.png"
     49                        data-setup="{}" >
     50                     <source src="{{ video.url }}" type="video/mp4">
     51                 </video>
     52         </div>
     53 
     54         <div class="course-info-main clearfix w has-progress">
     55             <div class="info-bar clearfix">
     56                 <div class="content-wrap clearfix">
     57                     <div class="content">
     58                         <div class="mod-tab-menu">
     59                             <ul class="course-menu clearfix">
     60                                 <li><a class="ui-tabs-active active" id="learnOn"
     61                                        href="{% url 'course:course_lesson' course.id %}"><span>章节</span></a></li>
     62                                 <li><a id="commentOn" class=""
     63                                        href="{% url 'course:course_comment' course.id %}"><span>评论</span></a></li>
     64                             </ul>
     65                         </div>
     66                         <div id="notice" class="clearfix">
     67                             <div class="l"><strong>课程公告:</strong> <a
     68                                     href="javascript:void(0)">Spring的文档以及相关的jar文件已上传</a></div>
     69                         </div>
     70 
     71                         <div class="mod-chapters">
     72                             {% for lesson in course.lesson_set.get_queryset %}
     73                                 <div class="chapter chapter-active">
     74                                     <h3>
     75                                         <strong><i class="state-expand"></i>{{ lesson.name }}</strong>
     76                                     </h3>
     77                                     <ul class="video">
     78 
     79                                         {% for video in lesson.video_set.get_queryset %}
     80                                             <li>
     81                                                 <a target="_blank" href='{% url 'course:video_play' video.id %}'
     82                                                    class="J-media-item studyvideo">{{ video.name }}
     83                                                     ({{ video.learn_times }})
     84                                                     <i class="study-state"></i>
     85                                                 </a>
     86                                             </li>
     87                                         {% endfor %}
     88 
     89                                     </ul>
     90                                 </div>
     91                             {% endfor %}
     92                         </div>
     93 
     94                     </div>
     95                     <div class="aside r">
     96                         <div class="bd">
     97 
     98                             <div class="box mb40">
     99                                 <h4>资料下载</h4>
    100                                 <ul class="downlist">
    101                                     {% for course_resource in course.courseresource_set.get_queryset %}
    102                                         <li>
    103                                             <span><i
    104                                                     class="aui-iconfont aui-icon-file"></i>&nbsp;&nbsp;{{ course_resource.name }}</span>
    105                                             <a href="{{ MEDIA_URL }}{{ course_resource.download }}" class="downcode"
    106                                                target="_blank" download="" data-id="274" title="">下载</a>
    107                                         </li>
    108                                     {% endfor %}
    109                                 </ul>
    110                             </div>
    111                             <div class="box mb40">
    112                                 <h4>讲师提示</h4>
    113                                 <div class="teacher-info">
    114                                     <a href="{% url 'org:org_teacher' course.teacher.id %}" target="_blank">
    115                                         <img src='{{ MEDIA_URL }}{{ course.teacher.image }}' width='80' height='80'/>
    116                                     </a>
    117                                     <span class="tit">
    118           <a href="{% url 'org:org_teacher' course.teacher.id %}" target="_blank">{{ course.teacher.name }}</a>
    119         </span>
    120                                     <span class="job">{{ course.teacher.work_position }}</span>
    121                                 </div>
    122                                 <div class="course-info-tip">
    123                                     <dl class="first">
    124                                         <dt>课程须知</dt>
    125                                         <dd class="autowrap">{{ course.you_need_know }}</dd>
    126                                     </dl>
    127                                     <dl>
    128                                         <dt>老师告诉你能学到什么?</dt>
    129                                         <dd class="autowrap">{{ course.teacher_tell }}</dd>
    130                                     </dl>
    131                                 </div>
    132                             </div>
    133 
    134 
    135                             <div class="cp-other-learned  js-comp-tabs">
    136                                 <div class="cp-header clearfix">
    137                                     <h2 class="cp-tit l">该课的同学还学过</h2>
    138                                 </div>
    139                                 <div class="cp-body">
    140                                     <div class="cp-tab-pannel js-comp-tab-pannel" data-pannel="course"
    141                                          style="display: block">
    142                                         <!-- img 200 x 112 -->
    143                                         <ul class="other-list">
    144 
    145                                             {% for relate_course in relate_courses %}
    146                                                 <li class="curr">
    147                                                     <a href="{% url 'course:course_detail' relate_course.id %}"
    148                                                        target="_blank">
    149                                                         <img src="{{ MEDIA_URL }}{{ relate_course.image }}"
    150                                                              alt="{{ relate_course.name }}">
    151                                                         <span class="name autowrap">{{ relate_course.name }}</span>
    152                                                     </a>
    153                                                 </li>
    154                                             {% endfor %}
    155 
    156                                         </ul>
    157                                     </div>
    158                                     <div class="cp-tab-pannel js-comp-tab-pannel" data-pannel="plan">
    159                                         <ul class="other-list">
    160 
    161                                         </ul>
    162                                     </div>
    163                                 </div>
    164                             </div>
    165 
    166                         </div>
    167                     </div>
    168                 </div>
    169                 <div class="clear"></div>
    170 
    171             </div>
    172 
    173         </div>
    174     </div>
    175 {% endblock %}
    View Code
  • 相关阅读:
    关于任意文件下载及上传漏洞
    一文掌握XSS
    WEB层知识点
    课程交流网站项目架构
    docker容器中启动uwsgi秒退
    mongoDB中update_one与find_one_update异同
    Vue集成CKEditor5源代码
    Vue的index.html与其他静态文件分离部署
    scrapy-redis分布式爬虫使用及docker swarm集群部署
    django中form组件的校验时raise ValidationError与self.add_error异同
  • 原文地址:https://www.cnblogs.com/Sweltering/p/9979810.html
Copyright © 2011-2022 走看看