Django+Xadmin打造在线教育系统(五)

课程相关功能实现

课程列表

创建课程相关的urls.py

path("course/", include('course.urls', namespace="course")),


course里面新建urls.py

from django.urls import path

from course.views import CourseListView

app_name = "courses"
urlpatterns = [
    # 课程列表url
    path('list/', CourseListView.as_view(), name="list"),

]

视图函数

from django.shortcuts import render
from django.views.generic import View

class CourseListView(View):
    def get(self, request):
        return render(request, "course-list.html")

course-list.html继承base.html
修改title,修改bread里面,content里面放course-list独有的
去后台添加一些课程
修改视图函数

class CourseListView(View):
    def get(self, request):
        all_course = Course.objects.all()
        return render(request, "course-list.html", {
            "all_course": all_course,

        })

course-list.html文件

    {% for course in all_course %}
        

{{ course.name }}

时长:{{ course.learn_times }} 学习人数:{{ course.students }}  
来自{{ course.course_org.name }} {{ course.fav_nums }}
{% endfor %}

分页功能

class CourseListView(View):
    def get(self, request):
        all_course = Course.objects.all()
        # 对课程进行分页
        # 尝试获取前台get请求传递过来的page参数
        # 如果是不合法的配置参数默认返回第一页
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # 这里指从allorg中取五个出来,每页显示5个
        p = Paginator(all_course,6 , request=request)
        courses = p.page(page)
        return render(request, "course-list.html", {
            "all_course":courses,

        })

在html中使用时注意object_list,此时的all_course已经不是一个queryset,而是一个purepage对象
页码的替换参考之前的分页,拿来用即可

排序功能

class CourseListView(View):
    def get(self, request):
        all_course = Course.objects.all()

        # 进行排序
        sort = request.GET.get('sort', "")
        if sort:
            if sort == "students":
                all_course = all_course.order_by("-students")
            elif sort == "hot":
                all_course = all_course.order_by("-click_nums")

        # 热门课程推荐
        hot_courses = Course.objects.all().order_by("-students")[:3]


        # 对课程进行分页
        # 尝试获取前台get请求传递过来的page参数
        # 如果是不合法的配置参数默认返回第一页
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # 这里指从allorg中取五个出来,每页显示5个
        p = Paginator(all_course,6 , request=request)
        courses = p.page(page)
        return render(request, "course-list.html", {
            "all_course":courses,
            "sort": sort,
            "hot_courses": hot_courses
        })
    
    
热门课程推荐
{% for hot_course in hot_courses %}

{{ hot_course.name }}

难度:{{ hot_course.get_degree_display }}
{% endfor %}

课程详情

模板替换,
路由配置

# 课程详情页
re_path('course/(?P\d+)/', CourseDetailView.as_view(), name="course_detail"),
class CourseDetailView(View):
    '''课程详情'''
    def get(self, request, course_id):
        course = Course.objects.get(id=int(course_id))
        # 课程的点击数加1
        course.click_nums += 1
        course.save()
        return  render(request, "course-detail.html", {
            'course':course,

        })

课程的章节数如何实现?

models.py中自定义方法

    def get_zj_nums(self):
        # 获取课程章节数的方法
        return self.lesson_set.all().count()

    # 获取学习这门课程的用户
    def get_learn_users(self):
        # 谁的里面添加了它做外键,他都可以取出来
        return self.usercourse_set.all()[:5]

添加课程类别字段

    category = models.CharField(max_length=20, default="", verbose_name="课程类别")

修改course-detail.html内容

    

{{ course.name }}

{{ course.desc }}
难度:{{ course.get_degree_display }} 学习人数:{{ course.students }}
  • 时     长:{{ course.learn_times }}
  • 章 节 数:{{ course.get_zj_nums }}
  • 课程类别:{{ course.category }}
  • 学习用户: {% for user_course in course.get_learn_users %} {% endfor %}
    
  • 课程详情
{{ course.detail }}

授课机构

CourseOrg model添加一个获取教师数的方法

    def get_teacher_nums(self):
        #获取机构的教师数
        return self.teacher_set.all().count()

授课机构显示

    

授课机构

世界名校,课程权威

{{ course.course_org.name }}

已收藏
  • 课  程  数:      {{ course.course_org.course_nums }}
  • 教  师  数:      {{ course.course_org.get_teacher_nums }}
  • 所在地区:  {{ course.course_org.address }}
  • 认       证 :   

相关课程推荐

定义课程的tag ,如果tag相同,那么是相关课程。

courses/models.py:

tag = models.CharField(max_length=15, verbose_name="课程标签", default="")
class CourseDetailView(View):
    '''课程详情'''
    def get(self, request, course_id):
        course = Course.objects.get(id=int(course_id))
        # 课程的点击数加1
        course.click_nums += 1
        course.save()
        # 课程标签
        # 通过当前标签,查找数据库中的课程
        tag = course.tag
        if tag:
            # 需要从1开始不然会推荐自己
            relate_courses = Course.objects.filter(tag=tag)[:3]
        else:
            relate_courses = []
        return  render(request, "course-detail.html", {
            'course':course,
            'relate_courses':relate_courses,
        })

前端

    
相关课程推荐
{% for relate_course in relate_courses %}

{{ relate_course.name }}

学习时长:{{ relate_course.learn_times }}
{% endfor %}

收藏功能

ajax

    
class CourseDetailView(View):
    '''课程详情'''
    def get(self, request, course_id):
        course = Course.objects.get(id=int(course_id))
        # 课程的点击数加1
        course.click_nums += 1
        course.save()
        # 课程标签
        # 通过当前标签,查找数据库中的课程
        has_fav_course = False
        has_fav_org = False

        # 必须是用户已登录我们才需要判断。
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course.id, fav_type=1):
                has_fav_course = True
            if UserFavorite.objects.filter(user=request.user, fav_id=course.course_org.id, fav_type=2):
                has_fav_org = True
        tag = course.tag
        if tag:
            # 需要从1开始不然会推荐自己
            relate_courses = Course.objects.filter(tag=tag)[:2]
        else:
            relate_courses = []
        return  render(request, "course-detail.html", {
            'course':course,
            'relate_courses':relate_courses,
            "has_fav_course": has_fav_course,
            "has_fav_org": has_fav_org,
        })

修改前端代码

    {% if has_fav_org %}
        已收藏
    {% else %}
        收藏
    {% endif %}

课程章节信息

章节信息,评论信息
模板替换

# 课程章节信息页
    re_path('info/(?P\d+)/', CourseInfoView.as_view(), name="course_info"),
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,
        })

修改开始学习链接

    

章节视频信息

为video表添加视频对应的url信息

url = models.CharField(max_length=200, default="" ,verbose_name="访问地址")

给Vedio添加一个学习时长的字段

# 使用分钟做后台记录(存储最小单位)前台转换
   learn_times = models.IntegerField(default=0, verbose_name="学习时长(分钟数)")

给Course添加一个获取章节的方法

    def get_course_lesson(self):
        #获取课程的章节
        return self.lesson_set.all()

给Lesson添加一个获取所有视频的方法

    def get_lesson_vedio(self):
        #获取章节所有视频
        return self.video_set.all()

后台添加视频信息
前端页面展示

    
{% for lesson in course.get_course_lesson %}

{{ lesson.name }}

{% endfor %}

资料下载

后台自行上传点文件

class CourseInfoView(View):
    def get(self,request,course_id):
        course = Course.objects.get(id=int(course_id))
        all_resources = CourseResource.objects.filter(course=course)
        return render(request,'course-video.html',{'course':course,'all_resources':all_resources})
    

资料下载

    {% for course_resource in all_resources %}
  •   {{ course_resource.name }} 下载
  • {% endfor %}

讲师提示

创建课程与讲师之间的关联,给Course添加一个Teacher外键

# Course
teacher = models.ForeignKey(Teacher,verbose_name='讲师',null=True,blank=True,on_delete=models.CASCADE)

给Course再添加两个字段 “课程须知”和“老师告诉你能学到什么”

    you_need_know = models.CharField(max_length=300, default="一颗勤学的心是本课程必要前提", verbose_name="课程须知")
    teacher_tell = models.CharField(max_length=300, default="按时交作业,不然叫家长", verbose_name="老师告诉你")

修改前端显示

    

讲师提示

{{ course.teacher.name }} {{ course.teacher.work_position }}
课程须知
{{ course.you_need_know }}
老师告诉你能学到什么?
{{ course.teacher_tell }}

课程评论页面

修改模板
配置url

#课程评论
    re_path('comment/(?P\d+)/', CommentsView.as_view(), name="course_comments"),
class CommentsView(View):
    def get(self, request, course_id):
        # 此处的id为表默认为我们添加的值。
        course = Course.objects.get(id=int(course_id))
        all_resources = CourseResource.objects.filter(course=course)
        return render(request, "course-comment.html", {
            "course": course,
            "all_resources": all_resources,
        })    

在course-vedio.html中修改 “章节”和“评论”的链接

    

发表评论功能
Ajax操作。如果发布成功就会刷新页面

# ajax方式添加评论
class AddCommentsView(View):
    def post(self, request):
        if not request.user.is_authenticated:
            # 未登录时返回json提示未登录,跳转到登录页面是在ajax中做的
            return HttpResponse('{"status":"fail", "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:
            course_comments = CourseComments()
            # get只能取出一条数据,如果有多条抛出异常。没有数据也抛异常
            # filter取一个列表出来,queryset。没有数据返回空的queryset不会抛异常
            course = Course.objects.get(id = int(course_id))
            # 外键存入要存入对象
            course_comments.course = course
            course_comments.comments = comments
            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')
# 添加课程评论,已经把参数放到post当中了
path('add_comment/', AddCommentsView.as_view(), name="add_comment"),

Ajax

    

相关课程推荐

CourseInfoView添加

        # 选出学了这门课的学生关系
        user_courses = UserCourse.objects.filter(course= course)
        # 从关系中取出user_id
        user_ids = [user_course.user_id for user_course in user_courses]
        # 这些用户学了的课程,外键会自动有id,取到字段
        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,
        })

修改前端代码

    

该课的同学还学过

把课程与用户关联起来

当用户点了“开始学习”之后,应该把这门课程与用户关联起来,在这之前应该需要做个判断,如果没有登录,则让用户先登录才可以。
如果是用函数方式写的话直接加个装饰器(@login_required)就可以,但是我们是用类的方式写的,必须用继承的方式

在utils目录下创建文件 mixin_utils.py(最基本的类都放在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)

然后让CourseInfoViewCommentsView都继承LoginRequiredMixin
继承后,没有登录的用户点“开始学习”,自动跳到login界面
把用户与课程关联起来

 # CourseInfoView
        # 查询用户是否已经学习了该课程
        user_courses = UserCourse.objects.filter(user=request.user,course=course)
        if not user_courses:
            # 如果没有学习该门课程就关联起来
            user_course = UserCourse(user=request.user,course=course)
            user_course.save()

视频播放页面

把course-paly.html拷贝到templates目录下
使用开源库video js,这里使用CDN



# 课程视频播放页
    path('video/(?P\d+)/', VideoPlayView.as_view(), name="video_play"),
    
  • {{ vedio.name }} ({{ vedio.learn_times }})
  • class VideoPlayView(LoginRequiredMixin, View):
        '''课程章节视频播放页面'''
        def get(self,request,video_id):
            video = Video.objects.get(id=int(video_id))
            #通过外键找到章节再找到视频对应的课程
            course = video.lesson.course
    
            course.students += 1
            course.save()
    
            # 查询用户是否已经学习了该课程
            user_courses = UserCourse.objects.filter(user=request.user,course=course)
            if not user_courses:
                # 如果没有学习该门课程就关联起来
                user_course = UserCourse(user=request.user,course=course)
                user_course.save()
    
            #相关课程推荐
            # 找到学习这门课的所有用户
            user_courses = UserCourse.objects.filter(course=course)
            # 找到学习这门课的所有用户的id
            user_ids = [user_course.user_id for user_course in user_courses]
            # 通过所有用户的id,找到所有用户学习过的所有过程
            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]
            # 通过所有课程的id,找到所有的课程,按点击量去五个
            relate_courses = Course.objects.filter(id__in=course_ids).order_by("-click_nums")[:5]
    
            # 资源
            all_resources = CourseResource.objects.filter(course=course)
            return render(request,'course-play.html',{
                'course':course,
                'all_resources':all_resources,
                'relate_courses':relate_courses,
                'video':video,
            })
    

    你可能感兴趣的:(Django+Xadmin打造在线教育系统(五))