零基础使用Django2.0.1打造在线教育网站

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

2018-08-11  本文已影响7人  啃饼小白

写在前面

本篇笔记我们将介绍课程详情页面的配置,这个页面和我们之前配置的页面差别不是很大,可以借鉴前面的配置。

本篇笔记对应于第十九篇代码,对应于github的位置是https://github.com/licheetools/eduline

总结一下

小伙伴们可能会问了,这篇笔记还没开始写怎么就开始总结了呢?是的,尽管没写但是我觉得非常有必要在这里总结一下,特别是对之前讲的信息的总结。后面随着开发进度的加快,一些东西我就不会详细介绍了,因为都是非常类似的操作。

我们现在可以理解MTV的模式就应该是这样子的:新建数据库字段(models)-->配置访问路径(urls) -->新建视图函数(views) --> 页面信息动态加载(templates),所以后面的操作就是这个过程,大家在学习的时候对此要有一个清醒的认识。

话不多说,我们正式进入今天的学习内容,走你。

课程列表页配置

老规矩,把前端资料里面的course-list.html页面拷贝到我们的templates文件夹里面,接着配置url,在eduline/urls.py文件新增如下代码:

# 课程相关应用path配置
path("course/", include('courses.urls', namespace="course")),

然后打开courses应用,在里面新建urls.py文件并在里面新增如下代码:

from django.urls import path, include, re_path
from .views import CourseListView

app_name = "courses"

urlpatterns = [
    path('list/', CourseListView.as_view(), name='course_list'),

]

现在打开courses/views.py文件,我们添加如下代码:

from django.shortcuts import render
from django.views.generic.base import View
# Create your views here.


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

运行一下我们的项目,在浏览器地址栏输入:http://127.0.0.1:8000/course/list/然后回车出现:

可以发现访问没有问题,但是样式并没有加载出来。我们仔细观察course_list.html页面之后发现它和之前的org_list.html页面一样是具有共同的头部和尾部,因此我们可以继承base.html页面。

在course_list.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>公开课</li>
            </ul>
        </div>
</section>
{% endblock %}

{% block content %}
    <section>   <!--这里面的 <section> 就是课程信息,是通过观测来的-->
{% endblock %}
就是这个样子:

然后是回到我们的courses/views.py文件,我们修改代码如下:

from django.shortcuts import render
from django.views.generic.base import View
# Create your views here.
from .models import Course


class CourseListView(View):
    def get(self, request):
        all_courses = Course.objects.all()
        return render(request, "course-list.html", {
            "all_courses": all_courses,
        })
回到course_list.html页面,修改代码为图示信息:

分页功能配置

直接仿照我们当时在org_list.html的配置,拷贝如下代码至courses/views.py文件里面:

from pure_pagination import Paginator, EmptyPage, PageNotAnInteger

# 对课程进行分页,尝试获取前端get请求传递过来的page参数
        # 如果是不合法的配置参数则默认返回第一页
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # 这里指从all_courses中取出来,每页显示9个
        p = Paginator(all_courses, 9, request=request)

        courses = p.page(page)
        return render(request, "course-list.html", {
            "all_courses": courses,
        })
接着打开course_list.html文件,修改代码为图示:

在html中注意此刻不再是all_courses,前面说过此时的all_courses已经不是一个queryset对象,而是一个purepage对象,所以应该用all_courses.object_list。

还有复制org_list的页面分页代码,并将all_orgs修改为all_courses,就是这段代码:

 <div class="pageturn">
                            <ul class="pagelist">
                                {% if all_courses.has_previous %}
                                    <li class="long"><a href="?{{ all_courses.previous_page_number.querystring }}">上一页</a>
                                    </li>
                                {% endif %}
                                {% for page in all_courses.pages %}
                                    {% if page %}
                                        {% ifequal page all_courses.number %}
                                            <li class="active"><a href="?{{ page.querystring }}">{{ page }}</a></li>
                                        {% else %}
                                            <li><a href="?{{ page.querystring }}">{{ page }}</a></li>
                                        {% endifequal %}
                                    {% else %}
                                        <li class="none"><a href="">...</a></li>
                                    {% endif %}
                                {% endfor %}
                                {% if all_courses.has_next %}
                                    <li class="long"><a href="?{{ all_courses.next_page_number.querystring }}">下一页</a></li>
                                {% endif %}
                            </ul>
                        </div>

排序功能的配置


和前面在org_list页面的配置一模一样,我们复制粘贴并修改一下那些代码,放到courses/views.py文件里面:

all_courses = Course.objects.all().order_by("-add_time") # 默认是按添加顺序反着排序
# 最热门和参与人数排名
        # 最热门hot根据点击数来判断
        # 参与人数是根据学习人数来判断
        sort = request.GET.get('sort', '')
        if sort:
            if sort == "students":
                all_courses = all_courses.order_by("-students")
            elif sort == "hot":
                all_courses = all_courses.order_by("-click_nums")

return render(request, "course-list.html", {
            "sort": sort,
        })

现在打开course_list.html文件,我们将上述功能和选中状态进行配置:

<ul class="tab_header">
                        <li class="{% ifequal sort '' %}active{% endifequal %}"><a href="?sort=">最新 </a></li>
                        <li class="{% ifequal sort 'hot' %}active{% endifequal %}"><a href="?sort=hot">最热门</a></li>
                        <li class="{% ifequal sort 'students' %}active{% endifequal %}"><a href="?sort=students">参与人数</a></li>
                    </ul>
就是这个样子:

热门课程推荐

打开courses/views.py文件,新增以下代码:

  # 热门课程推荐
        hot_courses = Course.objects.all().order_by("-students")[:3]
       return render(request, "course-list.html", {
            "hot_courses": hot_courses,
        })

然后打开course_list.html文件,将热门课程推荐进行动态加载:


运行一下我们的项目,在浏览器地址栏输入http://127.0.0.1:8000/course/list/回车,发现课程难度显示有问题:

我们需要修改{ hot_course.degree }}{ hot_course.get_degree_display }},这个字段的意思是说得到degree的字段显示,并不是得到它本身,事实上它本身为英文。(专门针对choices的显示)

现在刷新一下我们的页面,难度等级正常显示了,没有问题:

至此课程列表页的介绍到此结束,下面我们介绍课程详情页面。

课程详情页配置

老规矩,把前端资料里面的course-detail.html页面拷贝到我们的templates文件夹里面,正常情况下我们应该配置url,但是鉴于此处的course-detail.html页面会继承我们之前的course-list.html页面,所以我们就先把course-detail.html页面给配置完,然后才开始url的配置。

打开course-detail.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>{{ course.name }}</li>
            </ul>
        </div>
</section>
{% endblock %}

{% block content %}
    <section>
    <section>   <!--这里面的 <section> 就是课程信息,是通过观测来的-->
{% endblock %}

接着配置url,打开courses/urls.py文件并在里面新增如下代码:

from .views import CourseDetailView

 # 课程机构首页url
    re_path('detail/(?P<course_id>.*)/', CourseDetailView.as_view(), name="course_detail"),

现在书写我们的视图函数,打开courses/views.py文件,在里面添加如下代码:

# 课程详情页
class CourseDetailView(View):
    def get(self, request,course_id):  # 所有re_path在请求参数的时候必须带上id
        return render(request, "course-detail.html", {})
然后配置页面的跳转链接,我们希望可以从课程列表页面跳转进来,所以打开course_list.html页面,将图中信息修改为所示信息:

接下来修改我们的view(courses/views.py文件),准备页面信息的动态加载:

# 课程详情页
class CourseDetailView(View):
    def get(self, request, course_id):
#注意一下此处的id是数据库表默认为我们添加的
        course = Course.objects.get(id=int(course_id))
        return render(request, "course-detail.html", {
            "course": course,
        })

然后打开course_detail.html页面,使我们的数据得到动态加载并显示出来。

注意章节数和学习用户的获取方式:在courses/modles.py文件里面的Course类里面定义一个get-zj-nums方法:

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

还有学习用户的获取方式:我们之前在operation中专门定义了一个类UserCourse用于对用户学习作记录的。既然存在了这个类(数据库生成和迁移操作之后是一张表),那我们就可以采用获取学习章节数的方式来获取它。

同样在courses/modles.py文件里面的Course类里面定义一个get-learn-users方法:

     def get_learn_users(self):
        # 获取学习用户数,此处不用统计,我们只取出5个即可
        return self.usercourse_set.all()[:5] 
就是这个样子:
现在打开course_detail.html页面,将信息修改为图示那样:
然后去xadmin后台新增用户课程,记得把刚才展示的课程加里面去,便于我们观察是否成功显示:
还有一个问题,就是你现在点进这个页面,那么相应课程的点击数应该加1,所以在我们的view(courses/views.py文件),新增以下代码:
# 课程点击数增加
        course.click_nums += 1
        course.save()

就是这个样子:

授课机构的配置


注意教师数的获取方式:
注意章节数和学习用户的获取方式:在organization/modles.py文件里面的CourseOrg类里面定义一个get_teacher_nums方法:

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

然后html页面调用,采用如下代码:

{{ course.course_org.get_teacher_nums }}

当然如果你不想自定义函数,那也是可以的,你仅仅只需要在前端页面采用如下代码即可,是不是更简单:

{{ course.course_org.teacher_set.count }}

接下来我们完成右侧下面的相关课程推荐模块。

相关课程推荐

这个就是相关课程推荐的页面,我们接下来就是完成这个功能:

打开courses/views.py文件,在CourseDetailView函数里面新增用于实现相关课程推荐功能的代码:

# 相关课程推荐
        # 此处为course而不是Course,我们是用前面取出的课程
        tag = course.tag
        if tag:
#  这里必须从1开始不然会推荐自己,也就是索引0
            relate_courses = Course.objects.filter(tag=tag)[1:2]
        else:
            relate_courses = []
 return render(request, "course-detail.html", {
            "relate_courses": relate_courses,
        })

就是这个样子:


接着在course-detail.html页面修改页面展示信息:
{% for relate_course in relate_courses %}
                        <dl>
                            <dt>
                                <a target="_blank" href="{% url 'course:course_detail' relate_course.id %}">
                                    <img width="240" height="220" class="scrollLoading"
                                         src="{{ MEDIA_URL }}{{ relate_course.image }}"/>
                                </a>
                            </dt>
                            <dd>
                                <a target="_blank" href="{% url 'course:course_detail' relate_course.id %}">
                                    <h2>{{ relate_course.name }}</h2></a>
                                <span class="fl">学习时长:<i class="key">{{ relate_course.learn_times }}</i></span>
                            </dd>
                        </dl>
                    {% endfor %}
就是这个样子: 然后去xadmin后台或者数据库中将几个课程的tag修改为同一个,然后再运行一下我们的项目,就出现:

现在还差页面中的收藏和开始学习这两个功能的配置了,开始学习我们在下一篇介绍。

实现收藏功能

我们之前在课程机构里面配置过收藏的功能,如果不熟悉的小伙伴们可以回顾一下第十八篇:
零基础使用Django2.0.1打造在线教育网站(十八):机构详情页配置,这里我就快速介绍一下:
首先在course-detail.html页面底部添加如下代码:

{% block custom_js %}
    <script type="text/javascript">
        //收藏分享
        function add_fav(current_elem, fav_id, fav_type) {
            $.ajax({
                cache: false,
                type: "POST",
                url: "{% url "org:add_fav" %}",
                data: {'fav_id': fav_id, 'fav_type': fav_type},
                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' %}?next={{ request.path }}";
                        } else {
                            alert(data.msg)
                        }

                    } else if (data.status == 'success') {
                        current_elem.text(data.msg)
                    }
                },
            });
        }

        $('#jsLeftBtn').on('click', function () {
            add_fav($(this), {{ course.id }}, 1);
        });

        $('#jsRightBtn').on('click', function () {
            add_fav($(this), {{ course.course_org.id }}, 2);
        });

    </script>
{% endblock %}

然后再打开course/views.py文件,补充 CourseDetailView函数:

from operation.models import UserFavorite


# 是否收藏课程,默认为否
        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

return render(request, "course-detail.html", {
            "has_fav_course": has_fav_course,
            "has_fav_org": has_fav_org,
        })

就是这个样子:


接着打开course-detail.html页面,修改收藏的显示:
<div class="btn colectgroupbtn"  id="jsLeftBtn">
                                  {% if has_fav_course %}已收藏{% else %}收藏{% endif %}
                            </div>


<div class="btn  notlogin
                         "data-favid="14" id="jsRightBtn">
                         {% if has_fav_org %}已收藏{% else %}收藏{% endif %}
                    </div>
运行一下项目,两个都点击试试:

数据库已经有了,点击就没有了。

备注

知道为什么会出现这种情况么?那是因为jQuery 入口函数与 JavaScript 入口函数是有区别的:jQuery 的入口函数是在 html 所有标签(DOM)都加载之后,就会去执行。而JavaScript 的 window.onload 事件是等到所有内容,包括外部图片之类的文件加载完后,才会执行的。这里是js还未加载完就去执行,所以才出现的问题,放在底部就没问题了。

至此本篇关于课程详情页面的配置介绍就到此结束了,感谢你的赏阅。

本篇笔记对应于第十九篇代码,对应于github的位置是https://github.com/licheetools/eduline

上一篇下一篇

猜你喜欢

热点阅读