自定义分页器
参考文档: https://www.cnblogs.com/Dominic-Ji/articles/12035722.html
# 批量插入数据
bulk_create
★models.Book.objects.bulk_create(book)
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=32)
### --- ### --- ### --- ###
from django.test import TestCase
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ajax.settings")
import django
django.setup()
from app01 import models
# -- 一条条的添加10万条数据很慢很慢!!
# for i in range(100000):
# models.Book.objects.create(title="第%s本书" % i)
# -- ★ 批量添加10万条数据!
# ★★★★★与上面相比,只需要执行一次sql语句/只用操作一次数据库!!
book = []
for i in range(10000):
book_obj = models.Book(title="第%s本书" % i)
book.append(book_obj)
models.Book.objects.bulk_create(book)
# -- Ps:清空表中的数据 models.Book.objects.all().delete()
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
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
# 分页(简单版)
首先要明确:
1> get请求是可以携带参数的, 所以前端朝后端发送查看数据的同时可以携带一个参数告诉后端我们想看第几页的数据;
2> queryset对象是支持索引取值和切片操作的,但是不支持负数索引!!分页四要素: 当前页、总数量、每页条数、总页数
准备数据: 批量的往book表中插入 103条 数据!!
views.py
from django.shortcuts import render
from app01 import models
def index(request):
all_count = models.Book.objects.all().count() # -- 总数据有多少条
per_page = 10 # -- 每页展示多少条数据
# -- 计算出一共多少页 all_page
# 使用python的内置方法divmod
integer, mod = divmod(all_count, per_page) # -- all_count / per_page => (整数,余数)
if mod: # -- 有余数,则总页数加1
all_page = integer + 1
else:
all_page = integer
# -- current_page 当前第几页
# 获取用户想访问的页码,如果没有,默认展示第一页
current_page = request.GET.get('page', 1)
try: # -- 由于后端接受到的前端数据是字符串类型,所以我们这里做类型转换处理加异常捕获
current_page = int(current_page)
except Exception as e:
current_page = 1
# -- 需要对总数据进行切片操作,即需要确定切片起始位置和终止位置
start = (current_page - 1) * per_page # -- 当前页是从数据库的第几条数据开始
end = current_page * per_page # -- 当前页是到数据库的第几条数据结束(不包含尾数据)
# -- 切片是顾头不顾尾的!
# 当前实验数据是103条,共11页,最后一页的切片是[100,110],由于切片的特性,只取到103条,不会报错!
book_list = models.Book.objects.all()[start:end]
html = ""
for i in range(1, all_page + 1):
if i == current_page:
# -- class="active" 添加高亮
html += '<li class="active"><a href="?page=%s" >%s</a></li>' % (i, i)
else:
html += '<li><a href="?page=%s" >%s</a></li>' % (i, i)
return render(request, 'index.html', locals())
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
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
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Title</title>
</head>
<body>
<br>
{% for book in book_list %}
<p style="margin-left: 100px">
{{ book.title }}
</p>
{% endfor %}
{# 直接cv拷贝bootstrap的分页组件相关代码 #}
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{{ html|safe }}
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</body>
</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
34
35
36
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
扩展: 上面代码默认每页展示10条数据, 有个需求, 让根据用户的选择设定每页展示的条数..
解决 -- 在前端有个下拉框,让用户选择条数,将这个条数像当前页一样通过url参数传到后端.. ?page=1&per_page=10
# 分页类(优化版)
添加了上一页、下一页、首页、尾页等功能.
Ps: 自己写分页器可以使用该代码,在公司里,有现成的..
因为自定义的分页器代码属于第三方的,我们在根目录下创建 名为lib 或者 utils 的文件夹进行存放!!
utils.mypage.py
class Pagination(object):
def __init__(self, current_page, all_count, per_page_num=10, pager_count=8):
"""
封装分页相关数据
:param current_page: 当前页
:param all_count: 数据库中的数据总条数
:param per_page_num: 每页显示的数据条数
:param pager_count: 最多显示的页码个数
:return page_html_list: 前端分页栏代码(前端是需要使用Bootstrapt的!)
"""
try:
current_page = int(current_page)
except Exception as e:
current_page = 1
if current_page < 1:
current_page = 1
self.current_page = current_page
self.all_count = all_count
self.per_page_num = per_page_num
# -- 总页码
all_pager, tmp = divmod(all_count, per_page_num)
if tmp:
all_pager += 1
self.all_pager = all_pager
self.pager_count = pager_count
self.pager_count_half = int((pager_count - 1) / 2)
@property
def start(self):
return (self.current_page - 1) * self.per_page_num
@property
def end(self):
return self.current_page * self.per_page_num
def page_html(self):
# -- 如果总页码 < 11个:
if self.all_pager <= self.pager_count:
pager_start = 1
pager_end = self.all_pager + 1
# -- 总页码 > 11
else:
# -- 当前页如果<=页面上最多显示11/2个页码
if self.current_page <= self.pager_count_half:
pager_start = 1
pager_end = self.pager_count + 1
# -- 当前页大于5
else:
# -- 页码翻到最后
if (self.current_page + self.pager_count_half) > self.all_pager:
pager_end = self.all_pager + 1
pager_start = self.all_pager - self.pager_count + 1
else:
pager_start = self.current_page - self.pager_count_half
pager_end = self.current_page + self.pager_count_half + 1
page_html_list = []
# -- 添加前面的nav和ul标签
page_html_list.append('''
<nav aria-label='Page navigation>'
<ul class='pagination'>
''')
# -- 首页
first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
page_html_list.append(first_page)
# -- 上一页
if self.current_page <= 1:
prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
else:
prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)
page_html_list.append(prev_page)
# -- 当前页
for i in range(pager_start, pager_end):
if i == self.current_page:
temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
else:
temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
page_html_list.append(temp)
# -- 下一页
if self.current_page >= self.all_pager:
next_page = '<li class="disabled"><a href="#">下一页</a></li>'
else:
next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
page_html_list.append(next_page)
# -- 尾页
last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
page_html_list.append(last_page)
# -- 添加结束标签
page_html_list.append('''</nav></ul>''')
return ''.join(page_html_list)
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
84
85
86
87
88
89
90
91
92
93
94
95
96
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
84
85
86
87
88
89
90
91
92
93
94
95
96
前端分页栏点击的效果如下: (这里默认显示的页码为8个!)
views.py
from django.shortcuts import render
from app01 import models
from utils.mypage import Pagination
def index(request):
book_count = models.Book.objects.all().count() # -- 总数据有多少条
current_page = request.GET.get('page', 1) # -- 当前第几页
obj = Pagination(current_page, book_count)
book_list = models.Book.objects.all()[obj.start:obj.end]
page_html = obj.page_html()
return render(request, 'index.html', locals())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Title</title>
</head>
<body>
<br>
{% for book in book_list %}
<p style="margin-left: 100px">
{{ book.title }}
</p>
{% endfor %}
{{ page_html|safe }}
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Ps: Django的from组件进行表单校验参考链接 https://www.cnblogs.com/Dominic-Ji/p/9240365.html