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代码:
他是一个无序列表
<div class="pageturn">
<ul class="pagelist">
<li class="active"><a href="?page=1">1</a></li>
<li><a href="?page=2" class="page">2</a></li>
<li><a href="?page=3" class="page">3</a></li>
<li class="long"><a href="?page=2">下一页</a></li>
</ul>
</div>
在ul标签下添加:
{{ all_orgs.render }}
把其他的li标签的页码注释了运行后:
但是我们不用这个。哈哈!!
我们使用的时分页组件django-pure-pagination提供的代码。
但是要对它进行改造,改一些变量的名称。
{% if page_obj.has_previous %}
<a href="?{{ page_obj.previous_page_number.querystring }}" class="prev">‹‹ {% trans "previous" %}</a>
{% else %}
<span class="disabled prev">‹‹ {% trans "previous" %}</span>
{% endif %}
{% for page in page_obj.pages %}
{% if page %}
{% ifequal page page_obj.number %}
<span class="current page">{{ page }}</span>
{% else %}
<a href="?{{ page.querystring }}" class="page">{{ page }}</a>
{% endifequal %}
{% else %}
...
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<a href="?{{ page_obj.next_page_number.querystring }}" class="next">{% trans "next" %} ››</a>
{% else %}
<span class="disabled next">{% trans "next" %} ››</span>
{% endif %}
我们要把这个组件提供的逻辑代码和orglist原有的页码显示代码进行结合:
<ul class="pagelist">
{# 上一页 #}
{% if all_orgs.has_previous %}
<li class="long"><a href="?{{ all_orgs.previous_page_number.querystring }}"
class="page">上一页</a></li>
{% endif %}
{# 页码循环 #}
{% for page in all_orgs.pages %}
{% if page %}
{% ifequal page all_orgs.number %}
{# 用户点击的是否是当前页码 #}
<li class="active"><a
href="?{{ page.querystring }}">{{ page }}</a>
</li>
{% else %}
<li class="page"><a
href="?{{ page.querystring }}">{{ page }}</a>
</li>
{% endifequal %}
{% else %}
<li class="none">...</li>
{% endif %}
{% endfor %}
{# 下一页 #}
{% if all_orgs.has_next %}
<li class="long"><a href="?{{ all_orgs.next_page_number.querystring }}"
class="page">下一页</a></li>
{% endif %}
</ul>
分析:分页的页码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,要用做判断依据:
<a href="?city="><span class="{% ifequal category ''%}active2{% endifequal %}">全部</span></a>
<a href="?ct=pxjg&city="><span class="{% ifequal category 'pxjg'%}active2{% endifequal %}">培训机构</span></a>
<a href="?ct=gx&city="><span class="{% ifequal category 'gx'%}active2{% endifequal %}">高校</span></a>
<a href="?ct=gr&city="><span class="{% ifequal category 'gr'%}active2{% endifequal %}">个人</span></a>
把传过来的category在于其点击时传给后台的接口值进行比较,如果相等,那么class=‘active2’显示。形成高亮。默认全部按钮高亮。
运行:
点击‘高校’:
所在地区的筛选选项的实现
1.地区的显示
所在地区的显示相对于机构类别有所不同,他的选项是动态的,要从数据库中循环遍历显示。
那么找到所在地区部分的html代码,对它进行for循环的改造:
<div class="cont">
<a href="?ct="><span class="active2">全部</span></a>
{% for city in all_citys %}
<a href="?city={{ city.id }}&ct="><span class="">{{ city.name }}</span></a>
{% endfor %}
</div>
但是点击是没有什么效果的。
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值上。
也就是互绑。
网友评论