十四、授课教师功能
1、讲师列表页面
1.1 前端页面配置
将讲师列表页面teachers-list.html拷贝到templates下。
继承base页面,重写需要block的地方:
1.2 讲师列表接口
在organization/views.py中编写讲师列表的接口:
1 class TeacherListView(View): 2 """讲师列表""" 3 def get(self, request): 4 # 获取所有的讲师 5 all_teachers = Teacher.objects.all() 6 7 return render(request, \'teachers-list.html\', { 8 \'all_teachers\': all_teachers 9 })
配置url:
from .views import TeacherListView urlpatterns = [ re_path(\'teacher/list/\', TeacherListView.as_view(), name=\'teacher_list\'), # 讲师列表 ]
修改index.html中跳转到讲师列表页面的url:
在讲师列表页面需要显示讲师的年龄,需要在teacher的model中增加一个年龄的字段:
1 class Teacher(models.Model): 2 """机构老师""" 3 org = models.ForeignKey(CourseOrg, verbose_name=\'所属机构\', on_delete=models.CASCADE) 4 name = models.CharField(\'老师名\', max_length=50) 5 age = models.IntegerField(\'年龄\', default=25) 6 work_years =models.IntegerField(\'工作年限\', default=0) 7 work_company = models.CharField(\'就职公司\', max_length=50) 8 work_position = models.CharField(\'工作职位\', max_length=50) 9 points = models.CharField(\'教学特点\', max_length=50) 10 click_nums = models.IntegerField(\'点击数\', default=0) 11 fav_nums = models.IntegerField(\'收藏数\', default=0) 12 image = models.ImageField(\'头像\', upload_to=\'teacher/%Y/%m\', max_length=100, default=\'\') 13 add_time = models.DateTimeField(\'添加时间\', default=datetime.now) 14 15 class Meta: 16 verbose_name = \'教师\' 17 verbose_name_plural = verbose_name 18 19 def __str__(self): 20 return \'[{}]机构的教师:{}\'.format(self.org.name, self.name)
迁移数据库。
然后修改讲师列表页面显示讲师信息的代码:
1.3 分页功能
在讲师列表接口中完善分页的逻辑:
1 class TeacherListView(View): 2 """讲师列表""" 3 def get(self, request): 4 # 获取所有的讲师 5 all_teachers = Teacher.objects.all() 6 7 # 统计讲师的总数 8 teacher_nums = all_teachers.count() 9 10 # 分页 11 try: 12 page = request.GET.get(\'page\', 1) 13 except PageNotAnInteger: 14 page = 1 15 p = Paginator(all_teachers, 5, request=request) 16 teachers = p.page(page) 17 18 return render(request, \'teachers-list.html\', { 19 \'all_teachers\': teachers, 20 \'teacher_nums\': teacher_nums 21 })
在遍历讲师的时候需要加上object_list属性,否则在分页会抛出异常:
修改前端分页显示的代码:
1.4 排序功能
讲师可以根据人气进行排序,完善讲师列表接口中排序的逻辑:
1 class TeacherListView(View): 2 """讲师列表""" 3 def get(self, request): 4 # 获取所有的讲师 5 all_teachers = Teacher.objects.all() 6 7 # 统计讲师的总数 8 teacher_nums = all_teachers.count() 9 10 # 排序,按点击数排序 11 sort = request.GET.get(\'sort\', \'\') 12 if sort: 13 if sort == \'hot\': 14 all_teachers = all_teachers.order_by(\'-click_nums\') 15 16 # 分页 17 try: 18 page = request.GET.get(\'page\', 1) 19 except PageNotAnInteger: 20 page = 1 21 p = Paginator(all_teachers, 5, request=request) 22 teachers = p.page(page) 23 24 return render(request, \'teachers-list.html\', { 25 \'all_teachers\': teachers, 26 \'teacher_nums\': teacher_nums, 27 \'sort\': sort 28 })
修改讲师列表页面中按人气选中的状态显示代码:
在讲师列表页面右侧有讲师排行版,完善讲师列表接口中排行榜的逻辑:
1 class TeacherListView(View): 2 """讲师列表""" 3 def get(self, request): 4 # 获取所有的讲师 5 all_teachers = Teacher.objects.all() 6 7 # 统计讲师的总数 8 teacher_nums = all_teachers.count() 9 10 # 排序,按点击数排序 11 sort = request.GET.get(\'sort\', \'\') 12 if sort: 13 if sort == \'hot\': 14 all_teachers = all_teachers.order_by(\'-click_nums\') 15 16 # 讲师排行版 17 teacher_sorted = all_teachers.order_by(\'-click_nums\')[:3] 18 19 # 分页 20 try: 21 page = request.GET.get(\'page\', 1) 22 except PageNotAnInteger: 23 page = 1 24 p = Paginator(all_teachers, 5, request=request) 25 teachers = p.page(page) 26 27 return render(request, \'teachers-list.html\', { 28 \'all_teachers\': teachers, 29 \'teacher_nums\': teacher_nums, 30 \'sort\': sort, 31 \'teacher_sorted\': teacher_sorted 32 })
修改讲师列表页面中显示讲师排行榜的代码:
2、讲师详情页面
2.1 前端页面配置
将讲师详情页面teacher-detail.html拷贝到templates下。
继承base页面,重写需要block的地方:
2.2 讲师详情接口
1 class TeacherDetailView(View): 2 """讲师详情页面""" 3 def get(self, request, teacher_id): 4 # 根据前端的讲师id找到对应的讲师 5 teacher = Teacher.objects.get(id=int(teacher_id)) 6 7 # 获取该老师所有的课程 8 all_courses = Course.objects.filter(teacher=teacher) 9 10 # 讲师排行 11 teacher_sorted = Teacher.objects.all().order_by(\'-click_nums\')[:3] 12 13 return render(request, \'teacher-detail.html\', { 14 \'teacher\': teacher, 15 \'all_courses\': all_courses, 16 \'teacher_sorted\': teacher_sorted 17 })
配置url:
1 from .views import TeacherDetailView 2 3 urlpatterns = [ 4 re_path(\'teacher/detail/(?P<teacher_id>\d+)/\', TeacherDetailView.as_view(), name=\'teacher_detail\'), # 讲师详情 5 ]
在讲师列表页面修改点击讲师跳转到讲师详情页面的url:
修改讲师详情页面信息的显示代码:
2.3 收藏
在讲师详情页面可以收藏讲师,右侧可以收藏机构,完善讲师详情接口中收藏的判断逻辑:
1 class TeacherDetailView(View): 2 """讲师详情页面""" 3 def get(self, request, teacher_id): 4 # 根据前端的讲师id找到对应的讲师 5 teacher = Teacher.objects.get(id=int(teacher_id)) 6 7 # 获取该老师所有的课程 8 all_courses = Course.objects.filter(teacher=teacher) 9 10 # 讲师排行 11 teacher_sorted = Teacher.objects.all().order_by(\'-click_nums\')[:3] 12 13 # 讲师收藏、机构收藏 14 has_teahcer_faved = False 15 if UserFavorite.objects.filter(user=request.user, fav_type=3, fav_id=teacher_id): 16 has_teahcer_faved = True 17 has_org_faved = False 18 if UserFavorite.objects.filter(user=request.user, fav_type=2, fav_id=teacher.org.id): 19 has_org_faved = True 20 21 return render(request, \'teacher-detail.html\', { 22 \'teacher\': teacher, 23 \'all_courses\': all_courses, 24 \'teacher_sorted\': teacher_sorted, 25 \'has_teahcer_faved\': has_teahcer_faved, 26 \'has_org_faved\': has_org_faved 27 })
修改讲师详情页面中收藏的判断代码:
因为收藏操作是由前端通过ajax异步操作的,需要在讲师详情页面的最下面加上script代码:
1 {% block custom_js %} 2 <script type="text/javascript"> 3 //收藏分享 4 function add_fav(current_elem, fav_id, fav_type){ 5 $.ajax({ 6 cache: false, 7 type: "POST", 8 url:"{% url "org:add_fav" %}", 9 data:{\'fav_id\':fav_id, \'fav_type\':fav_type}, 10 async: true, 11 beforeSend:function(xhr, settings){ 12 xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}"); 13 }, 14 success: function(data) { 15 if(data.status == \'fail\'){ 16 if(data.msg == \'用户未登录\'){ 17 window.location.href="/login/"; 18 }else{ 19 alert(data.msg) 20 } 21 22 }else if(data.status == \'success\'){ 23 current_elem.text(data.msg) 24 } 25 }, 26 }); 27 } 28 29 $(\'#jsLeftBtn\').on(\'click\', function(){ 30 add_fav($(this), {{ teacher.id }}, 3); 31 }); 32 33 $(\'#jsRightBtn\').on(\'click\', function(){ 34 add_fav($(this), {{ teacher.org.id }}, 2); 35 }); 36 </script> 37 {% endblock %}