您现在的位置是: 网站首页 >Django >Django2.0.8+xadmin2实现在线学习网站 Django

【Django在线教育平台】13.课程内容页,该课程评论功能

admin2019年6月4日 14:08 Django | Html | JQuery 443人已围观

Django2.0.8+xadmin2实现在线学习网站简介 Django2.0.8+xadmin2实现在线学习网站,课程、讲师、机构、用户收藏功能。GitHub地址:https://github.com/xyliurui/OnlineLearningPlatform ;Django版本:2.0.8

## 课程内容页 ### 内容页面模板 创建course-content.html,同样继承base.html ```html {% for lesson in all_lesson %} <h6><b>{{ lesson.name }}</b></h6> <ul class="bullet-round-list padding-left-20 padding-bottom-15"> {% for video in lesson.get_lesson_video %} <li style="color: #d0d0d0"> <a target="_blank" href="{{ video.url }}">{{ forloop.parentloop.counter }}.{{ forloop.counter }} {{ video.name }}({{ video.learn_times }}分钟)</a> </li> {% endfor %} </ul> {% endfor %} ``` ![BLOG_20190604_140903_67](/media/blog/images/2019/06/BLOG_20190604_140903_67.png "博客图集BLOG_20190604_140903_67.png") ### 内容页面url ```python from .views import CourseListView, CourseDetailView, CourseContentView app_name = 'courses' urlpatterns = [ # 课程相关url path('list/', CourseListView.as_view(), name='course_list'), re_path('id/(?P<course_id>\d+)/detail/', CourseDetailView.as_view(), name="course_detail"), # 课程详情 re_path('id/(?P<course_id>\d+)/content/', CourseContentView.as_view(), name="course_content"), # 课程内容 ] ``` 详情页点击开始学习跳转到内容页 ```html <a href="{% url 'course:course_content' course.id %}" class="btn-round"> 开始学习</a> ``` ### 课程章节信息 章节`Lesson`模型中添加获取该章节视频的函数 ```python # 课程章节 class Lesson(models.Model): # 一个课程下有多个章节,需要用到一对多的关系,使用外键完成 course = models.ForeignKey(Course, on_delete=models.CASCADE, verbose_name='课程') name = models.CharField(max_length=100, verbose_name='章节名') add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') def get_lesson_video(self): # 获取章节视频 return self.video_set.all() class Meta: verbose_name_plural = verbose_name = '章节' def __str__(self): return '课程 ' + self.course.name + '的章节:' + self.name ``` ### 章节视频信息 视频模型中添加视频url,以及视频的学习实践 ```python # 课程视频 class Video(models.Model): lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE, verbose_name='章节') name = models.CharField(max_length=100, verbose_name='视频名') url = models.URLField(null=True, blank=True, verbose_name='访问地址') learn_times = models.IntegerField(default=0, verbose_name='学习时长(分钟数)') add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') class Meta: verbose_name_plural = verbose_name = '视频' def __str__(self): return '章节 ' + self.lesson.name + '的视频:' + self.name ``` 同步数据库 ```python manage.py@DjangoOnlineLearningPlatform > makemigrations courses manage.py@DjangoOnlineLearningPlatform > migrate courses ``` ### 课程关联讲师字段 在`Course`表中关联讲师的信息,用于讲师获取 ```python # 课程信息表 class Course(models.Model): DEGREE_CHOICES = ( ("cj", "初级"), ("zj", "中级"), ("gj", "高级") ) name = models.CharField(max_length=50, verbose_name='课程名') desc = models.CharField(max_length=300, verbose_name='课程描述') # 后面会改为富文本 detail = models.TextField(verbose_name='课程详情') degree = models.CharField(max_length=3, choices=DEGREE_CHOICES, verbose_name='课程难度') learn_times = models.IntegerField(default=0, verbose_name='学习时长(分钟数)') # 点击开始学习后记录学习人数 students = models.IntegerField(default=0, verbose_name='学习人数') fav_nums = models.IntegerField(default=0, verbose_name='收藏人数') image = models.ImageField(upload_to='course/%Y/%m', max_length=100, blank=True, null=True, verbose_name='封面图(160*160px)') # 点击到课程信息界面即需要记录点击数 click_nums = models.IntegerField(default=0, verbose_name='点击数') add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') course_org = models.ForeignKey(CourseOrg, null=True, blank=True, related_name='courses', on_delete=models.CASCADE, verbose_name='所属机构') category = models.ForeignKey(Category, null=True, blank=True, on_delete=models.SET_NULL, related_name='courses', verbose_name='课程类别') # 课程类别删除后课程该字段设置为null tags = models.ManyToManyField(Tag, related_name='courses', verbose_name='课程标签') teacher = models.ForeignKey(Teacher, related_name='courses', null=True, blank=True, on_delete=models.SET_NULL, verbose_name='讲师') class Meta: verbose_name = verbose_name_plural = '课程' def get_lesson_nums(self): # 获取课程章节数,如果章节模型中未定义关联名称(related_name)则直接使用字段名_set来获取 return self.lesson_set.all().count() def __str__(self): return self.name ``` 执行同步 ```python manage.py@DjangoOnlineLearningPlatform > makemigrations manage.py@DjangoOnlineLearningPlatform > migrate ``` ### 课程须知和老师言辞字段 ```python # 课程信息表 class Course(models.Model): DEGREE_CHOICES = ( ("cj", "初级"), ("zj", "中级"), ("gj", "高级") ) name = models.CharField(max_length=50, verbose_name='课程名') desc = models.CharField(max_length=300, verbose_name='课程描述') # 后面会改为富文本 detail = models.TextField(verbose_name='课程详情') degree = models.CharField(max_length=3, choices=DEGREE_CHOICES, verbose_name='课程难度') learn_times = models.IntegerField(default=0, verbose_name='学习时长(分钟数)') # 点击开始学习后记录学习人数 students = models.IntegerField(default=0, verbose_name='学习人数') fav_nums = models.IntegerField(default=0, verbose_name='收藏人数') image = models.ImageField(upload_to='course/%Y/%m', max_length=100, blank=True, null=True, verbose_name='封面图(160*160px)') # 点击到课程信息界面即需要记录点击数 click_nums = models.IntegerField(default=0, verbose_name='点击数') add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间') course_org = models.ForeignKey(CourseOrg, null=True, blank=True, related_name='courses', on_delete=models.CASCADE, verbose_name='所属机构') category = models.ForeignKey(Category, null=True, blank=True, on_delete=models.SET_NULL, related_name='courses', verbose_name='课程类别') # 课程类别删除后课程该字段设置为null tags = models.ManyToManyField(Tag, related_name='courses', verbose_name='课程标签') teacher = models.ForeignKey(Teacher, related_name='courses', null=True, blank=True, on_delete=models.SET_NULL, verbose_name='讲师') notes = models.CharField(max_length=20, default='人生苦短,我用Python!', verbose_name='课程须知') tell_you = models.CharField(max_length=20, default='', verbose_name='讲师告诉你学到了什么') class Meta: verbose_name = verbose_name_plural = '课程' def get_lesson_nums(self): # 获取课程章节数,如果章节模型中未定义关联名称(related_name)则直接使用字段名_set来获取 return self.lesson_set.all().count() def __str__(self): return self.name ``` 同步数据库 ```python manage.py@DjangoOnlineLearningPlatform > makemigrations courses manage.py@DjangoOnlineLearningPlatform > migrate courses ``` ### 课程内容视图 ```python # 课程内容---章节、视频、资源 class CourseContentView(View): def get(self, request, course_id): course = Course.objects.get(id=course_id) # 获取该课程的所有章节 all_lesson = course.lesson_set.all() # 获取该课程所有的下载资源 all_resource = course.courseresource_set.all() # 标记当前页,用于页面选中active current_access_url = 'course' return render(request, 'course-content.html', locals()) ``` ## 课程评论页 ### 评论展示页面模板 同样使用course-content.html,只是用选项卡的方式显示,这儿有个技巧,因为评论要分页,当后台获取到这个`page`这个参数的时候,就需要激活`comment`的选项卡 ```html <ul class="nav" role="tablist"> <li role="presentation" {% ifnotequal tab_choose 'comment' %} class="active" {% endifnotequal %}><a href="#course-lesson" role="tab" data-toggle="tab">章节</a></li> <li role="presentation" {% ifequal tab_choose 'comment' %} class="active" {% endifequal %}><a href="#course_comment" role="tab" data-toggle="tab">评论</a></li> </ul> <!-- Tab panes --> <div class="tab-content"> <div role="tabpanel" class="tab-pane fade {% ifnotequal tab_choose 'comment' %} in active {% endifnotequal %}" id="course-lesson"> <!-- List Details --> {% for lesson in all_lesson %} <h6><b>{{ lesson.name }}</b></h6> <ul class="bullet-round-list padding-left-20 padding-bottom-15"> {% for video in lesson.get_lesson_video %} <li style="color: #d0d0d0"> <a target="_blank" href="{{ video.url }}">{{ forloop.parentloop.counter }}.{{ forloop.counter }} {{ video.name }}({{ video.learn_times }}分钟)</a> </li> {% endfor %} </ul> {% endfor %} </div> <div role="tabpanel" class="tab-pane fade {% ifequal tab_choose 'comment' %} in active {% endifequal %}" id="course_comment"> <div class="comments" style="margin-top: 2px;"> <h6>{% if comment_nums > 0 %}已经有{{ comment_nums }}条评论啦{% else %}暂无评论{% endif %}</h6><br> <ul> {% for comment in all_comment_page.object_list %} <!-- Comments --> <li class="media" style="margin-top: 1px;"> <div class="media-left"> <a href="#" class="avatar"> <img src="{% if comment.user.image %}{{ comment.user.image.url }}{% else %}{% static 'platform/images/default-user.jpg' %}{% endif %}" style="width: 60px; height: auto" alt=""> </a> </div> <div class="media-body padding-left-20"> <h6>{{ comment.user.nick_name }}({{ comment.user.username }}) <span><i class="fa fa-bookmark-o"></i> {{ comment.add_time }} </span></h6> <p>{{ comment.comments }}</p> </div> </li> {% endfor %} </ul> <ul class="container pagination"> {% if all_comment_page.has_previous %} <li><a href="?{{ all_comment_page.previous_page_number.querystring }}" aria-label="Previous"> <i class="fa fa-angle-left"></i> </a></li> {% endif %} {% for page in all_comment_page.pages %} {% if page %} {% ifequal page all_comment_page.number %} <li><a class="active" href="?{{ page.querystring }}">{{ page }}</a></li> {% else %} <li><a href="?{{ page.querystring }}">{{ page }}</a></li> {% endifequal %} {% else %} <li><a href="">...</a></li> {% endif %} {% endfor %} {% if all_comment_page.has_next %} <li><a href="?{{ all_comment_page.next_page_number.querystring }}" aria-label="Next"> <i class="fa fa-angle-right"></i> </a></li> {% endif %} </ul> </div> </div> </div> ``` ![BLOG_20190604_140847_68](/media/blog/images/2019/06/BLOG_20190604_140847_68.png "博客图集BLOG_20190604_140847_68.png") ### 课程内容视图中评论展示CourseContentView(View) ```python # 课程内容---章节、视频、资源 class CourseContentView(View): def get(self, request, course_id): course = Course.objects.get(id=course_id) # 获取该课程的所有章节 all_lesson = course.lesson_set.all() # 获取该课程所有的下载资源 all_resource = course.courseresource_set.all() # 获取该课程所有的评论,最新发布排在前面 all_comment = course.coursecomments_set.all().order_by('-add_time') # 评论数量 comment_nums = all_comment.count() # 评论分页 try: page = request.GET.get('page', 1) except PageNotAnInteger: page = 1 # 每页显示5个 p = Paginator(all_comment, 5, request=request) all_comment_page = p.page(page) # tab选择标识,当进入分页的时候,说明已经进入评论页面,则在模板中需要active tab if request.GET.get('page'): tab_choose = 'comment' # 标记当前页,用于页面选中active current_access_url = 'course' return render(request, 'course-content.html', locals()) ``` ### 添加评论视图 发表评论功能 ajax操作。如果发布成功就会刷新页面。 新建view用于添加评论courses/views.py ```python # 添加评论 class AddCommentView(View): def post(self, request): if not request.user.is_authenticated: # 未登录时返回json提示未登录,跳转到登录页面是在ajax中做的 return HttpResponse('{"comment_status":"fail", "comment_msg":"用户未登录"}', content_type='application/json') course_id = request.POST.get('course_id', 0) comments = request.POST.get('comments', '') if int(course_id) > 0 and comments.strip(): course_comment = CourseComments() course_comment.course = Course.objects.get(id=course_id) course_comment.comments = comments course_comment.user = request.user course_comment.save() return HttpResponse('{"comment_status":"success", "comment_msg":"评论成功"}', content_type='application/json') else: return HttpResponse('{"comment_status":"fail", "comment_msg":"评论失败"}', content_type='application/json') ``` ### 添加评论url ```python from .views import CourseListView, CourseDetailView, CourseContentView, AddCommentView app_name = 'courses' urlpatterns = [ # 课程相关url path('list/', CourseListView.as_view(), name='course_list'), re_path('id/(?P<course_id>\d+)/detail/', CourseDetailView.as_view(), name="course_detail"), # 课程详情 re_path('id/(?P<course_id>\d+)/content/', CourseContentView.as_view(), name="course_content"), # 课程内容 path('add_comment/', AddCommentView.as_view(), name="add_comment"), # 添加评论,参数放在post中的 ] ``` ### 评论表单模板和ajax代码 ```html <h6>评论一下吧~</h6> <!-- FORM --> <form> <ul class="row"> <li class="col-sm-12"> <label> <textarea id="js_comment_value" name="comments" class="form-control" rows="3" placeholder="请输入评论" style="height: auto; max-width: 100%;"></textarea> </label> </li> <li class="col-sm-12 text-left"> <button type="button" class="btn-round" id="js_comment_button">发表评论</button> </li> </ul> </form> <script type="text/javascript"> $('#js_comment_button').on('click', function () { let comments = $('#js_comment_value').val(); if (comments === ''){ alert('评论不能为空'); return } $.ajax({ cache: false, type: 'POST', url: "{% url 'courses: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.comment_status === 'fail') { if (data.comment_msg === '用户未登录') { window.location.href = "{% url 'login' %}?next={{ request.path }}"; } else { alert(data.comment_msg); } } else if (data.comment_status === 'success') { window.location.reload(); //刷新当前页面 } }, }); }); </script> ``` ![BLOG_20190604_140838_29](/media/blog/images/2019/06/BLOG_20190604_140838_29.png "博客图集BLOG_20190604_140838_29.png")

很赞哦! (1)

文章交流

  • emoji
0人参与,0条评论

当前用户

未登录,点击   登录

站点信息

  • 建站时间:网站已运行792天
  • 系统信息:Linux
  • 后台程序:Python: 3.6.6
  • 网站框架:Django: 2.2.12
  • 文章统计:250 篇
  • 文章评论:45 条
  • 腾讯分析网站概况-腾讯分析
  • 百度统计网站概况-百度统计
  • 公众号:微信扫描二维码,关注我们
  • QQ群:QQ加群,下载网站的学习源码
返回
顶部
标题 换行 登录
网站