美文网首页Django在线教育平台
【Django在线教育平台】07.授课机构列表显示,分页、分类筛

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

作者: 吾星喵 | 来源:发表于2019-06-04 14:33 被阅读21次

    专题: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>
    

    相关文章

      网友评论

        本文标题:【Django在线教育平台】07.授课机构列表显示,分页、分类筛

        本文链接:https://www.haomeiwen.com/subject/skglxctx.html