2020-05-08--Django项目7--orglist内容分页,内容筛选

Orglist.html中内容的分页

问题描述:



也就是当列表中数据项很多时,我们不可能把他全部写在一页上,所以要对它进行分页,用户点击那一页的页码,就显示该页的内容。

1.分页组件-----django-pure-pagination

GitHub网址:
https://github.com/jamespacileo/django-pure-pagination

在我们之前也讲过分页操作,使用django自带的分页,但是为了美观,我们要使用这个分页组件。这个组件进行分页时页码不会全部显示,之前的分页会显示全部页码,不好看:


(1)安装组件
pip install django-pure-pagination

我们之前在requirments.txt中已经安装了该组件,所以这里无需下载。(我们每安装一个库或者组件都把它写到requirments.txt中,方便以后的项目部署)


(2)注册组件

在settings.pyz中的INSTALLED_APPS,添加一个:

'pure_pagination'
(3)分页组件的设置

在settings.py中的最后加上:

#分页组件相关的设置
PAGINATION_SETTINGS = {
    'PAGE_RANGE_DISPLAYED': 10,  #主分页部分显示几个
    'MARGIN_PAGES_DISPLAYED': 2,  #省略号前边或后边显示几个
    'SHOW_FIRST_PAGE_WHEN_INVALID': True,  #是否显示第一页
}

2.编写view操作分页

首先我们要分页,就不能在后端服务器中把所有的数据信息传给前台了,要先把数据分成若干部分,再传给前台html。

class OrgView(View):
    def get(self,request,*args,**kwargs):
        '''
        展示授课机构的列表页
        :param request:
        :param args:
        :param kwargs:
        :return:
        '''
        all_orgs = CourseOrg.objects.all()         #查询所有的机构信息
        org_nums = all_orgs.count()          #查询机构的个数
        all_citys = City.objects.all()       #查询所有的城市信息

        #分页部分
        #获取page,如果没找到或者出错都置page为1
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1

        #参数1:作用对象,参数2:单页显示数量,参数3:request
        p = Paginator(all_orgs, per_page=5,request=request)

        orgs = p.page(page)          #获取page页的信息


        return render(request, 'orglist.html',{
            'all_orgs':orgs,
            'org_nums':org_nums,
            'all_citys':all_citys
            })

解析:
(1)首先检测一下错误信息,保证每个page都正常显示.
(2)通过Paginator类实例化,对获取到的全部机构信息进行分割,每页5个
(3)通过Paginator的实例对象(p)中的方法page(页码)获取该页码的内容信息,最后传给模板进行重新进行数据绑定。

3.orglist.html列表信息分页显示的重构

在上一步后台的视图函数把分好的每页的数据信息传给了orglist.html。
当我们运行项目,点击进入到orglist.html时,会出现以下错误:



Page对象不可被迭代。

这是由于在服务器的view中,在没有分页的时候,我们传的是Queryset对象,可以被迭代(在orglist.html中我们使用for循环进行循环显示的),我们现在传值org为Page对象,不能被迭代。
解决:
在orglist.html修改for循环的循环对象:

all_orgs   ----->   all_orgs.objects.list

找到orglidst.html中的页码的html代码:
他是一个无序列表


在ul标签下添加:

{{ all_orgs.render }}

把其他的li标签的页码注释了运行后:



但是我们不用这个。哈哈!!
我们使用的时分页组件django-pure-pagination提供的代码。
但是要对它进行改造,改一些变量的名称。

 {% if page_obj.has_previous %}
        
    {% else %}
        ‹‹ {% trans "previous" %}
    {% endif %}
    {% for page in page_obj.pages %}
        {% if page %}
            {% ifequal page page_obj.number %}
                {{ page }}
            {% else %}
                {{ page }}
            {% endifequal %}
        {% else %}
            ...
        {% endif %}
    {% endfor %}
    {% if page_obj.has_next %}
        
    {% else %}
        {% trans "next" %} ››
    {% endif %}

我们要把这个组件提供的逻辑代码和orglist原有的页码显示代码进行结合:

    {# 上一页 #} {% if all_orgs.has_previous %}
  • 上一页
  • {% endif %} {# 页码循环 #} {% for page in all_orgs.pages %} {% if page %} {% ifequal page all_orgs.number %} {# 用户点击的是否是当前页码 #}
  • {{ page }}
  • {% else %}
  • {{ page }}
  • {% endifequal %} {% else %}
  • ...
  • {% endif %} {% endfor %} {# 下一页 #} {% if all_orgs.has_next %}
  • 下一页
  • {% endif %}

分析:分页的页码list分三部分:

  • 上一页
  • 页码列表
  • 下一页
    1.如果page对象有上一页,那麽就显示列表项--上一页,并且链接到上一页。并加上css样式class=“long”
    2.循环page对象的页码(pages),该页码存在(存在与否与settings中的设置有关),并且是用户点击的页码,那么就显示该循环项{{page}},并加上css样式class=“active”(加黑)。如果不是用户当前页,也显示,但是加上css样式class=“page”(不加黑)。
    页码不存在,那么就显示 ...。
    3.如果page对象有下一页,那麽就显示列表项--下一页,并且链接到下一页。并加上css样式class=“long”
    修改settings中的页码设置:
    主分页只显示3个页码,其他分区显示1个
#分页组件相关的设置
PAGINATION_SETTINGS = {
    'PAGE_RANGE_DISPLAYED': 3,  #主分页部分显示几个
    'MARGIN_PAGES_DISPLAYED': 1,  #省略号前边或后边显示几个
    'SHOW_FIRST_PAGE_WHEN_INVALID': True,  #是否显示第一页
}

orglist一共有6个数据,每页只显示1个
运行效果图:



这些内容及代码在github的分页组件上都有。

机构类别筛选选项内容的实现

当我们访问到orglist.html时,默认显示全部的,在实际开发中,会设置选项进行筛选内容,方便查找。
我们首先找到该部分的html代码:



查看接口为get请求,也就是说当用户点击某一个筛选选项时,其访问服务器的url后会加上该选项的信息。
所以我们要在后端view视图中进行操作获取。
打开apps/organizations/view.py:
我们要把获取筛选信息的逻辑代码写在分页之前,查询数据库数据之后。因为分页是针对于即将要显示与前台的数据,所以用户筛选后的信息也一样要分页。

#筛选选项--类别
        category = request.GET.get('ct','')    #获取前台接口数据
        if category:
            # 过滤类别为用户选择的数据
            all_orgs = all_orgs.filter(category=category)

解析:使用GET方法进行获取前端传过来的数据,如果没有,默认'',如果该字段存在,那么使用ORM进行筛选并再赋给all_orgs,传给前台页面。
运行:



筛选完成。
但是有一个小问题:当我们点击筛选选项时,高亮还是默认全部的选项。
所以我们要在html页面做css样式的判断。
高亮的css:



解决:
首先我们要判断用户点的是哪个按钮,唯一的辨识就是用户点击后传到后台的接口数据--category,所以在后台把该值传过来。

在前台的css,要用做判断依据:

全部
培训机构
高校
个人

把传过来的category在于其点击时传给后台的接口值进行比较,如果相等,那么class=‘active2’显示。形成高亮。默认全部按钮高亮。
运行:
点击‘高校’:


所在地区的筛选选项的实现

1.地区的显示

所在地区的显示相对于机构类别有所不同,他的选项是动态的,要从数据库中循环遍历显示。
那么找到所在地区部分的html代码,对它进行for循环的改造:

全部 {% for city in all_citys %} {{ city.name }} {% endfor %}

但是点击是没有什么效果的。

2.编写地区筛选的视图逻辑

当用户点击了某个地区以后,要显示相应的内容信息,就要对视图进行修改:
在机构类别的筛选逻辑之后,添加以下代码:

 #对所在城市进行筛选
        city_id = request.GET.get('city','')          #获取前台用户点击的选项数据
        if city_id:             #如果存在,
            if city_id.isdigit():          #如果该数据合法,
                 all_orgs = all_orgs.filter(city_id=city_id)         #过滤用户选择的数据

运行:
点击所在地区的选项----沈阳市


数据显示成功。
但是出现了三个问题:

  • 1.机构数量的显示没有变化,一直显示的是所有的机构数量,没有根据相应的选项进行实时更新。
  • 2.当点击机构类别的选项后,再点击所在地区的选项,机构类别的选项重新刷新为全部,也就是说两种筛选选项没有联动起来,都是独立的。
  • 3.高亮的显示没有变换

(1)机构数量实时更新。

首先我们分析,之前我们从后台传递过来的数量一直都是所有的总数,所以我们要改变数量计算的位置,也就是在分页之前,经过两层过滤后的机构总数。

#显示最后绑定到网页上的机构数量。
org_nums = all_orgs.count()

运行:
点击培训机构后:


筛选选项联动

分析:

选项没有联动的原因?
我们查看前端的选项接口:ct和city。机构类别的city没有赋值,所在地区的ct没有赋值。
现在想:当用户点击了机构类别选项后,再点击所在地区选项,要想联动的话,就要把点击机构类别ct的值传给所在地区选项的ct值,用户再点击所在地区的选项时,ct和city都有了值。反之,也是一个道理,先点击地区选项,就要把city.id传给机构类别选项的city,再点击时,也就有了两个值。

解决:
机构类别传给后台的值为category,那么把category从后台传给前台,再绑定到地区的ct值上。
所在地区传给后台的值为city_id,那么把city_id从后台传给前台,但是city_id就是city.id,它本身就是动态的,(根据用户点击的选项不同city.id就不同)
所以把city.id绑定到机构类别的city值上。



也就是互绑。

高亮

你可能感兴趣的:(2020-05-08--Django项目7--orglist内容分页,内容筛选)