Django-分頁組件
一、仿django分页功能自己实现

urls.py
|
1
2
3
4
5
6
7
8
9
|
from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index.html$', views.index), ] |
views.py
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
from django.shortcuts import renderfrom app01 import models# Create your views here.USER_LIST = []#创建数据999条for i in range(999): temp = {'name':'root'+str(i),'age':i } #加到userlist列表中 USER_LIST.append(temp)def index(request): #每页显示10条数据 per_page_count = 10 #current-page 当有页 current_page = request.GET.get('p') #数字运算要转成int类型 current_page = int(current_page) #如果是第1页,索引0-9,就是1-10的数 #p=1 #0,10 0-9 取索引 #p=2 #大于等于10,小于20就是10-19 #10,20 10-19 #start 开始页数 end=结束页数 #如果p=1-1=0 start = (current_page - 1) * per_page_count #1 * 10=10 end = current_page*per_page_count #数据切片,每次显示10页 data = USER_LIST[start:end] #上一页 prev_pager = current_page -1 #下一页 next_pager = current_page +1 return render(request,'index.html',{'user_list':data,'prev_pager':prev_pager,'next_pager':next_pager }) |
index.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <ul> {% for row in user_list %} <li>{{ row.name }}-{{ row.age }}</li> {% endfor %} </ul> <a href="/index.html?p={{ prev_pager }}">上一页</a> <a href="/index.html?p={{ next_pager }}">下一页</a></body></html> |
二、利用django自带分页组件实现分页功能
使用分页器Paginator:
在视图中使用 Paginator来为查询集分页。我们提供视图以及相关的模板来展示如何展示这些结果。
|
1
2
3
4
5
|
Paginator常用属性per_page: 每页显示条目数量count: 数据总个数num_pages:总页数page_range:总页数的索引范围,页码的范围,从1开始,例如[1, 2, 3, 4]。 |
Paginator所需参数:
|
1
2
|
object_list 一个列表,元祖或则Django 的Queryset 对象 或则其他对象带有 count() or __len__()的方法per_page :就是1页显示几条数据 |
Paginator对象的方法:
|
1
|
page(number) :返回在提供的下标处的Page对象,下标以1开始。 |
使用page对象方法:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
Page.has_next()如果有下一页,则返回True。Page.has_previous()如果有上一页,返回 True。Page.has_other_pages()如果有上一页或下一页,返回True。Page.next_page_number()返回下一页的页码。如果下一页不存在,抛出InvalidPage异常。Page.previous_page_number()返回上一页的页码。如果上一页不存在,抛出InvalidPage异常。Page.start_index()返回当前页上的第一个对象,相对于分页列表的所有对象的序号,从1开始。比如,将五个对象的列表分为每页两个对象,第二页的start_index()会返回3。Page.end_index()返回当前页上的最后一个对象,相对于分页列表的所有对象的序号,从1开始。 比如,将五个对象的列表分为每页两个对象,第二页的end_index() 会返回 4。 |
属性
|
1
2
3
4
5
6
7
8
|
Page.object_list当前页上所有对象的列表。Page.number当前页的序号,从1开始。Page.paginator相关的Paginator对象。 |
代码示例:

Django内置分页:Paginator、Page

urls.py
|
1
2
3
4
5
6
7
8
9
|
from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r'^admin/', admin.site.urls), # url(r'^index.html$', views.index), url(r'^index1.html$', views.index1), ] |
views.py
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
from django.shortcuts import renderfrom django.shortcuts import redirectfrom django.shortcuts import HttpResponsefrom app01 import models# Create your views here.USER_LIST = []#创建数据999条for i in range(999): temp = {'name':'root'+str(i),'age':i } #加到userlist列表中 USER_LIST.append(temp)def index1(request): from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger #全部数据:USER_LIST,=>得出共有多少条数据 # per_page: 每页显示条目数量 # count: 数据总个数 # num_pages:总页数 # page_range:总页数的索引范围,如: (1,10),(1,200) # page: page对象 (是否具有下一页,是否有上一页) current_page = request.GET.get('p') #Paginator对象,里面封装了上面那些值,把USER_LIST对象传过来了,显示10页 paginator = Paginator(USER_LIST,10) try: #page对象 #posts配置对象(current_page用户可能填些不合法的字段) #paginator通过拿到了page对象,把current_page传进来 posts = paginator.page(current_page) # has_next 是否有下一页 # next_page_number 下一页页码 # has_previous 是否有上一页 # previous_page_number 上一页页码 # object_list 分页之后的数据列表,已经切片好的数据 # number 当前页 # paginator paginator对象 #表示你填的东西不是个整数 except PageNotAnInteger: posts = paginator.page(1) #空页的时候,表示你看完了,显示最后一页 except EmptyPage: posts = paginator.page(paginator.num_pages) return render(request,'index1.html' ,{'posts':posts}) |
index1.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body> <ul> {% for row in posts.object_list %} <li>{{ row.name }}-{{ row.age }}</li> {% endfor %} </ul> {% include 'include/pager.html' %}</body></html> |
pager.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
{% if posts.has_previous %} <a href="/index1.html?p={{ posts.previous_page_number }}">上一页</a> {% else %} <a href="#">上一页</a>{% endif %}{% if posts.has_next %} <a href="/index1.html?p={{ posts.next_page_number }}">下一页</a>{% endif %}<span> {{ posts.number }} / {{ posts.paginator.num_pages }}</span>{#切片完后,就叫object_list#} |
三、扩展Django内置分页


urls.py
|
1
2
3
4
5
6
7
|
from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/$', views.listing),] |
views.py
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
from django.shortcuts import renderfrom django.core.paginator import Paginator,EmptyPage,PageNotAnInteger# Create your views here.#模拟测试网页数据USER_LIST = []for i in range(1,999): temp = {"name":"root"+str(i),"age":i} USER_LIST.append(temp)class CustomPaginator(Paginator): def __init__(self,current_page,per_pager_num,*args,**kwargs): # per_pager_num 显示的页码数量 self.current_page = int(current_page) self.per_pager_num = int(per_pager_num) super(CustomPaginator,self).__init__(*args,**kwargs) def pager_num_range(self): ''' 自定义显示页码数 第一种:总页数小于显示的页码数 第二种:总页数大于显示页数 根据当前页做判断 a 如果当前页大于显示页一半的时候 ,往右移一下 b 如果当前页小于显示页的一半的时候,显示当前的页码数量 第三种:当前页大于总页数 :return: ''' if self.num_pages < self.per_pager_num: return range(1,self.num_pages+1) half_part = int(self.per_pager_num/2) if self.current_page <= half_part: return range(1,self.per_pager_num+1) if (self.current_page+half_part) > self.num_pages: return range(self.num_pages-self.per_pager_num+1,self.num_pages) return range(self.current_page-half_part,self.current_page+half_part+1)def listing(request): current_page = request.GET.get('p') paginator = CustomPaginator(current_page,11,USER_LIST,10) try: paginator = paginator.page(current_page) #获取前端传过来显示当前页的数据 except PageNotAnInteger: # 如果有异常则显示第一页 paginator = paginator.page(1) except EmptyPage: # 如果没有得到具体的分页内容的话,则显示最后一页 paginator = paginator.page(paginator.num_pages) return render(request,'index.html',{"users":paginator}) |
index.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title></head><body><ul> {% for user in users.object_list %} <li>{{ user.name }}-{{ user.age }}</li> {% endfor %} {% if users.has_previous %} <a href="/index?p={{ users.previous_page_number }}">上一页</a> {% endif %} {% for number in users.paginator.pager_num_range %} {% if number == users.number %} <a href="/index?p={{ number }}" style="font-size: 33px">{{ number }}</a> {% else %} <a href="/index?p={{ number }}" >{{ number }}</a> {% endif %} {% endfor %} {% if users.has_next %} <a href="/index?p={{ users.next_page_number }}">下一页</a> {% endif %} <span>{{ users.number }} /{{ users.paginator.num_pages }}</span></ul></body></html> |
没加特效:

二、自定义分页器
效果:

分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。
|
1
2
3
4
5
6
7
|
1、设定每页显示数据条数2、用户输入页码(第一页、第二页...)3、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置4、在数据表中根据起始位置取值,页面上输出数据 |
需求,需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
1、设定每页显示数据条数2、用户输入页码(第一页、第二页...)3、设定显示多少页号4、获取当前数据总条数5、根据设定显示多少页号和数据总条数计算出,总页数6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置7、在数据表中根据起始位置取值,页面上输出数据8、输出分页html,如:[上一页][1][2][3][4][5][下一页] |
代码示例:

代码:
urls.py
|
1
2
3
4
5
6
7
8
|
from django.conf.urls import urlfrom django.contrib import adminfrom app01 import viewsurlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index2.html$', views.index2),] |
views.py
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
from django.shortcuts import renderfrom django.core.paginator import Paginator, EmptyPage, PageNotAnInteger#这里用的是手动生成数据,生产环境到数据库中去取数据就可以啦USER_LIST = []for i in range(1,666): temp = {'name':'root'+str(i), 'age':i} USER_LIST.append(temp)def index2(request): from app01.pager import Pagination current_page = request.GET.get('p') page_obj = Pagination(666,current_page) data_list = USER_LIST[page_obj.start():page_obj.end()] return render(request,'index2.html',{'data':data_list,'page_obj':page_obj}) |
pager.py
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
class Pagination(object): def __init__(self,totalCount,currentPage,perPageItemNum=10,maxPageNum=7): # 数据总个数 self.total_count = totalCount # 当前页 try: v = int(currentPage) if v <= 0: v = 1 self.current_page = v except Exception as e: self.current_page = 1 # 每页显示的行数 self.per_page_item_num = perPageItemNum # 最多显示页面 self.max_page_num = maxPageNum def start(self): return (self.current_page-1) * self.per_page_item_num def end(self): return self.current_page * self.per_page_item_num @property def num_pages(self): """ 总页数 :return: """ # 666 # 10 a,b = divmod(self.total_count,self.per_page_item_num) if b == 0: return a return a+1 def pager_num_range(self): # self.num_pages() # self.num_pages # 当前页 #self.current_page # 最多显示的页码数量 11 #self.per_pager_num # 总页数 # self.num_pages if self.num_pages < self.max_page_num: return range(1,self.num_pages+1) # 总页数特别多 5 part = int(self.max_page_num/2) if self.current_page <= part: return range(1,self.max_page_num+1) if (self.current_page + part) > self.num_pages: return range(self.num_pages-self.max_page_num+1,self.num_pages+1) return range(self.current_page-part,self.current_page+part+1) def page_str(self): page_list = [] first = "<li><a href='/index2.html?p=1'>首页</a></li>" page_list.append(first) if self.current_page == 1: prev = "<li><a href='#'>上一页</a></li>" else: prev = "<li><a href='/index2.html?p=%s'>上一页</a></li>" %(self.current_page-1,) page_list.append(prev) for i in self.pager_num_range(): if i == self.current_page: temp = "<li class='active'><a href='/index2.html?p=%s'>%s</a></li>" %(i,i) else: temp = "<li><a href='/index2.html?p=%s'>%s</a></li>" % (i, i) page_list.append(temp) if self.current_page == self.num_pages: nex = "<li><a href='#'>下一页</a></li>" else: nex = "<li><a href='/index2.html?p=%s'>下一页</a></li>" % (self.current_page + 1,) page_list.append(nex) last = "<li><a href='/index2.html?p=%s'>尾页</a></li>" %(self.num_pages,) page_list.append(last) return ''.join(page_list) |
index2.html
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css" /></head><body> <ul> {% for row in data %} <li>{{ row.name }}-{{ row.age }}</li> {% endfor %} </ul> <ul class="pagination pagination-sm"> {{ page_obj.page_str|safe }} </ul> <div style="height: 300px;"></div></body></html> |
总结:分页时需要做三件事:
- 创建处理分页数据的类
- 根据分页数据获取数据
- 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]
Django-分頁組件的更多相关文章
- ASP.NET MVC 5 實作 GridView 分頁
本文用 ASP.NET MVC 5 實作一個 GridView,功能包括: 分頁(paging).關鍵字過濾(filtering).排序(sorting).AJAX 非同步執行,外觀上亦支援 Resp ...
- 何解決 LinqToExcel 發生「無法載入檔案或組件」問題何解決 LinqToExcel 發生「無法載入檔案或組件」問題
在自己的主機上透過 Visual Studio 2013 與 IISExpress 開發與測試都還正常,但只要部署到測試機或正式機,就是沒辦法順利執行,卡關許久之後找我協助.我發現錯誤訊息確實很「一般 ...
- 使用LINQ 對List分頁/區
listview之類的服務器控件分頁自不用多說,拖拖控件改改屬性分分鐘的事.就不浪費大家時間了. 這裏只寫大概思路及關鍵代碼了. LINQ裏有一個對集合進行分區的操作可用於分頁. page ...
- [深入浅出Windows 10]分屏控件(SplitView)
4.18 分屏控件(SplitView) 分屏控件(SplitView)是Windows 10新增的控件类型,也是Windows 10通用应用程序主推的交互控件,通常和一个汉堡按钮搭配作为一种抽屉式菜 ...
- 用Razor語法寫範本-RazorEngine組件介紹【转——非常好,可以用它来代替NVelocity】
RazorEngine 官網網址:http://razorengine.codeplex.com 在找到RazorEngine之前曾經想過其他的方案,如T4與V8 Engine載jquery.temp ...
- Gridview分頁保存選項
#region //'Revision: 1.00 Created Date: 2013/08/02 Created ID: Una [#1300071]增加多選框 /// <summary&g ...
- IOS开发之XCode学习013:步进器和分栏控件
此文学习来源为:http://study.163.com/course/introduction/1002858003.htm 此工程文件实现功能: 1.定义UIStepper和UISegmente ...
- vue組件
組件有局部組件和全局組件,全局組件,其它的元素能夠調用. Prop父組件子組件看不大明白.
- 用Razor語法寫範本-RazorEngine組件介紹
最近剛好有要寫寄Email的程式,在代碼中寫HTML覺得很呆,抽出代碼外寫到txt或html檔當範本,由程式執行時在載入檔案時用Regex換關鍵字又覺得不夠好用,而且因為有時會有要判斷一些條件,就會寫 ...
随机推荐
- python高效学习路线图
- [codeforces/gym/101350/L]维护“凸包”
题目链接:http://codeforces.com/gym/101350/problems 给定n个墙,每个墙有一个高度,要支持动态修改墙的高度和查询这个“容器”能盛多少水. (队友)观察发现,能盛 ...
- shell脚本实现轮询查看进程是否结束
功能需求: 一个shell脚本,为了使用多进程,启动十几个后台运行的程序,为了防止脚本比后台进程提前结束造成不可预估的影响,现要判断是否多个后台执行的已知进程已经结束,并在所有进程结束后做出相应操作. ...
- 详解ListView加载网络图片的优化
我们来了解一些ListView在加载大量网络图片的时候存在的常见问题: 1.性能问题,ListView的滑动有卡顿,不流畅,造成非常糟糕的用户体验. 2.图片的错位问题. 3.图片太大,加载Bitma ...
- ZooKeeper食谱(八)
使用ZooKeeper构造高级别应用的指南 在这个文章中,你将会发现使用ZooKeeper来实现高级别功能的指南.所有的它们在客户端上被实现而不需要ZooKeeper特别的支持.希望社区将注意到这些约 ...
- MySQL新建用户,授权
登录MySQL mysql -u root -p 添加新用户 允许本地 IP 访问 localhost, 127.0.0.1 create user 'test'@'localhost' identi ...
- 【51NOD-0】1019 逆序数
[算法]离散化+树状数组(求逆序对) [题解]经典,原理是统计在i之前插入的且值≤i的个数,然后答案就是i-getsum(i) #include<cstdio> #include<a ...
- CCC2018游记
day (-1) 晚上睡觉没盖被子 day 0 2018年2月13日 下午放学回来感到一阵头痛,一量体温结果发烧了,感觉很蓝瘦,居然在CCC前一天生病. 本来注册了账号想打practise的,结果又 ...
- JQGrid 导出Excel 获取筛选条件
需求描述:页面加载后,进行相关数据搜索,要求点击导出按钮后 下载Excel文件. 思路:希望在点击[导出Excel]按钮时,获取到表格搜索时的filters内容. 在百度.api.jqgrid.js ...
- js_md5加密和base64的加密解密
1.最近有些人在爬我们公司的数据,然有了这个md5加密的小需求.为什么叫小需求呢?嗯,之前没做过,会以为很复杂. 其实,是想多了. 2.前端md5加密,其实也并不是安全的,因为代码是可见的.也就是说, ...