【Django在线教育平台】07.授课机构列表显示,分页、分类筛选、排序功能

专题:Django2.0.8+xadmin2实现在线学习网站

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

更多内容请点击 我的博客 查看,欢迎来访。

授课机构功能实现

定义父模板base.html

用户其他模板扩展

机构列表基础

机构列表展示模板org-list.html

该模板继承base.html,使用{% extends 'base.html' %}

机构列表视图OrgListView(View)

organization/views.py

from django.shortcuts import render

from django.views.generic.base import View


class OrgListView(View):
    def get(self, request):
        return render(request, 'org-list.html')

机构列表url

修改主url,配置课程机构首页url

from organization.views import OrgListView


urlpatterns = [
    path('admin/', admin.site.urls),
    path('xadmin/', xadmin.site.urls),
    path('', TemplateView.as_view(template_name='index.html'), name='index'),
    # path('login/', TemplateView.as_view(template_name='login.html'), name='login'),
    # path('login/', user_login, name='login'),
    path('login/', LoginView.as_view(), name='login'),  # 基于类方法实现登录,这里是调用它的方法
    path('register/', RegisterView.as_view(), name='register'),
    re_path('register/active/(?P<active_code>.*)/', ActiveUserView.as_view(), name='user_active'),  # 激活
    path('captcha/', include('captcha.urls')),
    path('forgetpwd/', ForgetPwdView.as_view(), name='forgetpwd'),  # 忘记密码
    re_path('forgetpwd/reset/(?P<active_code>.*)/', RestpwdView.as_view(), name='resetpwd'),  # 密码重置验证
    path('modify_pwd/', ModifypwdView.as_view(), name="modify_pwd"),  # 密码修改

    path('org/list/', OrgListView.as_view(), name="org_list"),  # 机构列表
]

这样,访问 http://127.0.0.1:8000/org/list/ 即可查看机构列表

机构列表数据展示

确定由后台传过来的动态数据:授课机构列表本身, 授课机构的排名,所在地区(后台取出所有地区), 机构类别写成静态,因为一般不怎么变动。

在xadmin中添加城市信息,课程信息。

机构models中添加机构类别

organization/models.py

# 课程机构信息
class CourseOrg(models.Model):
    ORG_CHOICES = (
        ("pxjg", "培训机构"),
        ("gx", "高校"),
        ("gr", "个人"),
    )

    name = models.CharField(max_length=50, verbose_name='机构名称')
    desc = models.TextField(verbose_name='机构描述')
    category = models.CharField(choices=ORG_CHOICES, max_length=10, default='pxjg', verbose_name='机构类别')
    click_nums = models.IntegerField(default=0, verbose_name='点击数')
    fav_nums = models.IntegerField(default=0, verbose_name='收藏数')
    image = models.ImageField(upload_to='org/%Y/%m', max_length=100, verbose_name='封面图')
    address = models.CharField(max_length=150, verbose_name='机构地址')
    city = models.ForeignKey(CityDict, on_delete=models.CASCADE, verbose_name='所在城市')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')

    class Meta:
        verbose_name_plural = verbose_name = '课程机构'

    def __str__(self):
        return self.name

然后需要进行数据同步

manage.py@DjangoOnlineLearningPlatform > makemigrations
manage.py@DjangoOnlineLearningPlatform > migrate

完善机构列表视图

将列表里的静态数据变成后台获取的动态数据

organization/views.py

from .models import CourseOrg, CityDict


class OrgListView(View):
    def get(self, request):
        # 查找所有的机构
        all_org = CourseOrg.objects.all()
        # 取出所有城市
        all_city = CityDict.objects.all()
        # 机构类别
        all_category = list(map(lambda x: {'code': x[0], 'explain': x[1]}, CourseOrg.ORG_CHOICES))
        return render(request, 'org-list.html', locals())

模板中进行数据填充org-list.html

<div class="short-lst">
    <ul>
        <li><b>机构类别</b></li>
        <li><a href="?category=&city="> 全部 </a></li>
        {% for category in all_category %}
            <li><a href="?category={{ category.code }}&city="> {{ category.explain }} </a></li>
        {% endfor %}
    </ul>
</div>
<div class="short-lst">
    <ul>
        <li><b>所在地区</b></li>
        <li><a href="?category=&city="> 全部 </a></li>
        {% for city in all_city %}
            <li><a href="?category=&city={{ city.id }}"> {{ city.name }} </a></li>
        {% endfor %}
    </ul>
</div>


<div class="short-lst">
    <h2>授课机构<small>(共{{ all_org.count }}家)</small></h2>
    <ul>
        <!-- Short List -->
        <li>
            <p>全部</p>
        </li>
        <li>
            <p>学习人数↓</p>
        </li>
        <li>
            <p>课程数↓</p>
        </li>
    </ul>
</div>


{% for org in all_org %}
    <div class="product">
        <article>
            <!-- Product img -->
            <div class="media-left">
                <div class="item-img"><img class="img-responsive" src="{{ org.image.url }}" alt=""></div>
            </div>
            <!-- Content -->
            <div class="media-body">
                <div class="row">
                    <!-- Content Left -->
                    <div class="col-sm-7"><span class="tag"></span>
                        <h4><a href="#.">{{ org.name }}</a></h4>
                        <!-- Reviews -->

                        <ul class="bullet-round-list">
                            <li>课程数:xx</li>
                            <li>学习人数:xx</li>
                            <li>地址:</li>
                            <li>经典课程</li>
                        </ul>
                    </div>
                    <!-- Content Right -->
                    <div class="col-sm-5 text-center">
                        <div class="position-center-center">
                            <a href="#." class="btn-round">联系</a>
                        </div>
                    </div>
                </div>
            </div>
        </article>
    </div>
{% endfor %}

BLOG_20190604_135852_84

列表分页功能

首先需要安装相应的库

pip install django-pure-pagination

分页设置

修改settings.py添加分页app:pure_pagination

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'users',
    'courses',
    'organization',
    'operation',

    'xadmin',
    'crispy_forms',
    'reversion',
    'captcha',
    'pure_pagination',
]


PAGINATION_SETTINGS = {
    'PAGE_RANGE_DISPLAYED': 10,
    'MARGIN_PAGES_DISPLAYED': 2,
    'SHOW_FIRST_PAGE_WHEN_INVALID': True,
}
  • PAGE_RANGE_DISPLAYED是总共会显示多少个page。(包括省略号,包括两边和中间)
  • MARGIN_PAGES_DISPLAYED是旁边会显示多少个。
  • SHOW_FIRST_PAGE_WHEN_INVALID当输入页数不合法是否要跳到第一页

视图中分页实现

参照官方的文档

from pure_pagination import Paginator, EmptyPage, PageNotAnInteger

from .models import CourseOrg, CityDict


class OrgListView(View):
    def get(self, request):
        # 查找所有的机构
        all_org = CourseOrg.objects.all()
        # 取出所有城市
        all_city = CityDict.objects.all()
        # 机构类别
        all_category = list(map(lambda x: {'code': x[0], 'explain': x[1]}, CourseOrg.ORG_CHOICES))

        # 机构数量
        org_nums = all_org.count()

        # 对课程机构进行分页
        # 尝试获取前台get请求传递过来的page参数
        # 如果是不合法的配置参数默认返回第一页
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # 从列表中取5个出来,也就是每页显示5个
        p = Paginator(all_org, 5, request=request)
        all_org = p.page(page)
        return render(request, 'org-list.html', locals())

html配置分页

<h2>授课机构<small>(共{{ org_nums }}家,本页显示{{ all_org.object_list.count }}家)</small></h2>

{% for org in all_org.object_list %}
    # ....
{% endofr %}

<!-- pagination -->
<ul class="pagination">
    {% if all_org.has_previous %}
        <li><a href="?{{ all_org.previous_page_number.querystring }}" aria-label="Previous"> <i class="fa fa-angle-left"></i> </a></li>
    {% endif %}

    {% for page in all_org.pages %}
        {% if page %}
            {% ifequal page all_org.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_org.has_next %}
        <li><a href="?{{ all_org.next_page_number.querystring }}" aria-label="Next"> <i class="fa fa-angle-right"></i> </a></li>
    {% endif %}
</ul>

机构列表不再是objects,而是all_org.object_list

BLOG_20190604_135839_53

分类筛选功能

直接在url中添加参数,例如当用户点击某一个city时对应加上参数city的id

<li><a href="?category=&city={{ city.id }}"> {{ city.name }} </a></li>

后台处理类别筛选

class OrgListView(View):
    def get(self, request):
        # 查找所有的机构
        all_org = CourseOrg.objects.all()
        # 取出所有城市
        all_city = CityDict.objects.all()
        # 机构类别
        all_category = list(map(lambda x: {'code': x[0], 'explain': x[1]}, CourseOrg.ORG_CHOICES))

        # 处理类别筛选
        category_code = request.GET.get('category', '')
        if category_code:
            all_org = all_org.filter(category=category_code)

        # 机构数量
        org_nums = all_org.count()

        # 对课程机构进行分页
        # 尝试获取前台get请求传递过来的page参数
        # 如果是不合法的配置参数默认返回第一页
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # 从列表中取5个出来,也就是每页显示5个
        p = Paginator(all_org, 5, request=request)
        all_org = p.page(page)
        return render(request, 'org-list.html', locals())

后台处理城市筛选

class OrgListView(View):
    def get(self, request):
        # 查找所有的机构
        all_org = CourseOrg.objects.all()
        # 取出所有城市
        all_city = CityDict.objects.all()
        # 机构类别
        all_category = list(map(lambda x: {'code': x[0], 'explain': x[1]}, CourseOrg.ORG_CHOICES))

        # 处理类别筛选,取回的是字符串
        category_code = request.GET.get('category', '')
        if category_code:
            all_org = all_org.filter(category=category_code)

        # 处理城市筛选,取回的是city的ID
        city_id = request.GET.get('city', '')
        if city_id:
            all_org = all_org.filter(city=city_id)

        # 机构数量
        org_nums = all_org.count()

        # 对课程机构进行分页
        # 尝试获取前台get请求传递过来的page参数
        # 如果是不合法的配置参数默认返回第一页
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # 从列表中取5个出来,也就是每页显示5个
        p = Paginator(all_org, 5, request=request)
        all_org = p.page(page)
        return render(request, 'org-list.html', locals())

模板中处理两种筛选

已经选中的进行标记

<div class="short-lst">
    <ul>
        <li><b>机构类别</b></li>
        <li><a href="?category=&city={{ city_id }}" {% ifequal category_code '' %} style="color: #BEBEBE" {% endifequal %}> 全部 </a></li>
        {% for category in all_category %}
            <li><a href="?category={{ category.code }}&city={{ city_id }}" {% ifequal category_code category.code %} style="color: #BEBEBE" {% endifequal %}> {{ category.explain }} </a></li>
        {% endfor %}
    </ul>
</div>
<div class="short-lst">
    <ul>
        <li><b>所在地区</b></li>
        <li><a href="?category={{ category_code }}&city=" {% ifequal city_id '' %} style="color: #BEBEBE" {% endifequal %}> 全部 </a></li>
        {% for city in all_city %}
            <li><a href="?category={{ category_code }}&city={{ city.id }}" {% ifequal city_id city.id|stringformat:'i' %} style="color: #BEBEBE" {% endifequal %}> {{ city.name }} </a></li>
        {% endfor %}
    </ul>
</div>

BLOG_20190604_135827_76

由于我们使用的是分页库,这里变动page的时候url中其他参数不会变化

例如 访问 http://127.0.0.1:8000/org/list/?category=pxjg&city= 如果这时候点第2也, 则url会跳转到 http://127.0.0.1:8000/org/list/?category=pxjg&city=&page=2

进行城市与分类的联动:

  • 当选择全部类别的时候,就只通过当前城市id。
  • 当选择全部城市的时候,就只通过当前类别id。
  • 当两者都选的时候使用&连接。

课程机构排序

学习人数,课程数

organization/models.py

模型中添加排序字段

CourseOrg模型中添加两个字段studentscourse_nums

# 课程机构信息
class CourseOrg(models.Model):
    ORG_CHOICES = (
        ("pxjg", "培训机构"),
        ("gx", "高校"),
        ("gr", "个人"),
    )

    name = models.CharField(max_length=50, verbose_name='机构名称')
    desc = models.TextField(verbose_name='机构描述')
    category = models.CharField(choices=ORG_CHOICES, max_length=10, default='pxjg', verbose_name='机构类别')
    click_nums = models.IntegerField(default=0, verbose_name='点击数')
    fav_nums = models.IntegerField(default=0, verbose_name='收藏数')
    students = models.IntegerField(default=0, verbose_name='学习人数')
    course_nums = models.IntegerField(default=0, verbose_name='课程数数')
    image = models.ImageField(upload_to='org/%Y/%m', max_length=100, blank=True, null=True, verbose_name='封面图')
    address = models.CharField(max_length=150, verbose_name='机构地址')
    city = models.ForeignKey(CityDict, on_delete=models.CASCADE, verbose_name='所在城市')
    add_time = models.DateTimeField(default=datetime.now, verbose_name='添加时间')

    class Meta:
        verbose_name_plural = verbose_name = '课程机构'

    def __str__(self):
        return self.name

然后执同步

manage.py@DjangoOnlineLearningPlatform > makemigrations organization
manage.py@DjangoOnlineLearningPlatform > migrate organization

视图中增加排序OrgListView(View)

class OrgListView(View):
    def get(self, request):
        # 查找所有的机构
        all_org = CourseOrg.objects.all()
        # 取出所有城市
        all_city = CityDict.objects.all()
        # 机构类别
        all_category = list(map(lambda x: {'code': x[0], 'explain': x[1]}, CourseOrg.ORG_CHOICES))

        # 热门机构,选择点击数最多的3个机构显示到右边
        hot_org = all_org.order_by('-click_nums')[:3]

        # 处理类别筛选,取回的是字符串
        category_code = request.GET.get('category', '')
        if category_code:
            all_org = all_org.filter(category=category_code)

        # 处理城市筛选,取回的是city的ID
        city_id = request.GET.get('city', '')
        if city_id:
            all_org = all_org.filter(city=city_id)

        # 排序,按照学习人数或者课程数排序
        sort = request.GET.get('sort', '')
        if sort:
            if sort == 'students':
                all_org = all_org.order_by('-students')
            elif sort == 'courses':
                all_org = all_org.order_by('-course_nums')

        # 机构数量
        org_nums = all_org.count()

        # 对课程机构进行分页
        # 尝试获取前台get请求传递过来的page参数
        # 如果是不合法的配置参数默认返回第一页
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # 从列表中取5个出来,也就是每页显示5个
        p = Paginator(all_org, 5, request=request)
        all_org = p.page(page)
        return render(request, 'org-list.html', locals())

模板中排序url修改

<div class="short-lst">
    <h2>授课机构<small>(共{{ org_nums }}家,本页显示{{ all_org.object_list.count }}家)</small></h2>
    <ul>
        <!-- Short List -->
        <li>
            <p><a href="?category={{ category_code }}&city={{ city_id }}" {% ifequal sort '' %} style="font-weight: bold" {% endifequal %}> 全部 </a></p>
        </li>
        <li>
            <p><a href="?sort=students&category={{ category_code }}&city={{ city_id }}" {% ifequal sort 'students' %} style="color: #BEBEBE" {% endifequal %}> 学习人数 ↓</a></p>
        </li>
        <li>
            <p><a href="?sort=courses&category={{ category_code }}&city={{ city_id }}" {% ifequal sort 'courses' %} style="color: #BEBEBE" {% endifequal %}>课程数 ↓</a></p>
        </li>
    </ul>
</div>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值