Django 的分页和自定义分页组件
一 自定义分页
后台代码
def index(req):
data = list(range(999)) # 数据源 以列表示例
current_page_num = req.GET.get('p', None) # 获取当前页码
if not current_page_num:
current_page_num = 1
else:
current_page_num = int(current_page_num)
all_page_num = 100 # 手动设定的全部页数
page_info_num = 10 # 手动设定的每页显示条数
start = (current_page_num - 1) * page_info_num # 切片开始位置
end = start + page_info_num # 切片结束位置
data_list = data[start:end] # 切片
if current_page_num == 1: # 上一页页码
after = current_page_num
else:
after = current_page_num - 1
if current_page_num == all_page_num: # 下一页页码
next = current_page_num
else:
next = current_page_num + 1
return render(req, 'index.html', locals())
前端代码
<body>
<ul>
{% for i in data_list %}
<li>{{ i }}</li>
{% endfor %}
</ul>
<a href="/index?p={{ after }}">上一页</a>
<a href="/index?p={{ next }}">下一页</a>
</body>
二 Django自带分页组件
后台代码
from django.core.paginator import Paginator, EmptyPage
def index1(req):
data = list(range(999)) # 数据源 以列表示例
current_page_num = req.GET.get('p', None) # 当前页码
if not current_page_num:
current_page_num = 1
else:
current_page_num = int(current_page_num)
# 分页器 - -类
# 实例化产生一个对象
# 两个参数: object_list:对象列表, per_page: 每页显示的条数
paginator = Paginator(data, 10)
# 对象内的属性
# 数据总条数100条
print('数据总数量', paginator.count)
# 总页数 10 页
print('总页数', paginator.num_pages)
# 页码数的列表
print('页码列表', paginator.page_range)
# 取到第 x= 页, 返回一个Page对象
current_page = paginator.page(current_page_num)
# 当前页码内所有的数据
print('数据列表', current_page.object_list)
# 是否有下一页
print('是否有下一页', current_page.has_next())
# 是否有上一页
print('是否有上一页', current_page.has_previous())
# 下一页页码数
print('下一页的页码', current_page.next_page_number())
# 上一页的页码数
print('上一页的页码', current_page.previous_page_number())
data_list = current_page.object_list # 当前页面要显示的数据
if current_page.has_previous(): # 上一页页码
after = current_page.previous_page_number()
else:
after = current_page_num
if current_page.has_next(): # 下一页页码
next1 = current_page.next_page_number()
else:
next1 = current_page_num
return render(req, 'index1.html', locals())
前台代码
<body>
<ul>
{% for i in data_list %}
<li>{{ i }}</li>
{% endfor %}
</ul>
<a href="/index1?p={{ after }}">上一页</a>
<a href="/index1?p={{ next1 }}">下一页</a>
</body>
三 扩展Django自带分页组件
后台代码
from django.core.paginator import Paginator, EmptyPage
class my_Paginator(Paginator):
'''
继承Django的Paginator类
扩展功能,添加一个返回当前页页码下表列表
'''
def __init__(self, current_page, pages, *args, **kwargs):
self.current_page_num = current_page # 当前页码
self.pages = pages # 每页页码下标数量
super(my_Paginator, self).__init__(*args, **kwargs)
def page_num_range(self):
'''
返回当前页页码下表列表
:return:
'''
temp = self.pages // 2
if self.num_pages < self.pages:
return range(1, self.num_pages + 1)
if temp >= self.current_page_num:
return range(1, self.pages + 1)
if self.current_page_num >= self.num_pages - temp:
return range(self.num_pages - self.pages + 1, self.num_pages + 1)
return range(self.current_page_num - temp, self.current_page_num + temp + 1)
def index2(req):
data = list(range(100)) # 数据源 以列表示例
current_page_num = req.GET.get('p', None) # 当前页码
if not current_page_num:
current_page_num = 1
else:
current_page_num = int(current_page_num)
paginator = my_Paginator(current_page_num, 5, data, 10) # 创建分页对象
current_page = paginator.page(paginator.current_page_num) # 获得当前页对象
data_list = current_page.object_list # 获得当前页面数据列表
pages_list = list(paginator.page_num_range()) # 获得当前页面页码下标列表
if current_page.has_previous(): # 上一页页码
after = current_page.previous_page_number()
else:
after = current_page_num
if current_page.has_next(): # 下一页页码
next1 = current_page.next_page_number()
else:
next1 = current_page_num
return render(req, 'index2.html', locals())
前台代码
<body>
<ul>
{% for i in data_list %}
<li>{{ i }}</li>
{% endfor %}
</ul>
<a href="/index2?p={{ after }}">上一页</a>
{% for page in pages_list %}
{% if page == current_page_num %}
<a style="font-size: 30px" href=/index2?p={{ page }}>{{ page }}</a>
{% else %}
<a href=/index2?p={{ page }}>{{ page }}</a>
{% endif %}
{% endfor %}
<a href="/index2?p={{ next1 }}">下一页</a>
</body>
四 自定义分页
自定义分页类
class my_Paginator:
'''
自定义分页组件
'''
def __init__(self, data_list, info_num_page, page_num, current_page_num):
self.data_list = data_list # 要分页的数据
self.info_num_page = info_num_page # 每页数据的数量
self.page_num = page_num # 每页分页下标数量
self.current_page_num = current_page_num # 当前页码
self.start = self.info_num_page * (self.current_page_num - 1)
self.end = self.info_num_page * self.current_page_num
@property
def num_pages(self):
'''
返回总页数
:return:
'''
a, b = divmod(len(self.data_list), self.info_num_page)
if b:
return a + 1
return a
@property
def current_page_data_list(self):
'''
返回当前页的数据列表
:return:
'''
return self.data_list[self.start:self.end]
@property
def next_page(self):
'''
下一页页码
:return:
'''
if self.current_page_num + 1 >= self.num_pages or self.current_page_num <= 0:
return self.num_pages
return self.current_page_num + 1
@property
def previous_page(self):
'''
上一页页码
:return:
'''
if self.current_page_num - 1 <= 1 or self.current_page_num > self.num_pages:
return 1
return self.current_page_num - 1
@property
def page_num_range(self):
'''
返回当前页下标列表
:return:
'''
temp = self.page_num // 2
if self.num_pages < self.page_num:
return range(1, self.num_pages + 1)
if temp >= self.current_page_num:
return range(1, self.page_num + 1)
if self.current_page_num >= self.num_pages - temp:
return range(self.num_pages - self.page_num + 1, self.num_pages + 1)
return range(self.current_page_num - temp, self.current_page_num + temp + 1)
后台代码
from app0.Paginator import my_Paginator as my_paginator
def index3(req):
data = list(range(100)) # 以列表为数据源
current_page_num = req.GET.get('p', None) # 当前页码
if not current_page_num:
current_page_num = 1
else:
current_page_num = int(current_page_num)
paginator = my_paginator(data, 10, 5, current_page_num) # 实例自定义分页组件对象
data_list = paginator.current_page_data_list # 当前页面数据
pages_list = paginator.page_num_range # 当前页面下表列表
after = paginator.previous_page # 上一页页码
next1 = paginator.next_page # 下一页页码
return render(req, 'index3.html', locals())
前台代码
<body>
<ul>
{% for i in data_list %}
<li>{{ i }}</li>
{% endfor %}
</ul>
<a href="/index3?p={{ after }}">上一页</a>
{% for page in pages_list %}
{% if page == current_page_num %}
<a style="font-size: 30px" href=/index3?p={{ page }}>{{ page }}</a>
{% else %}
<a href=/index3?p={{ page }}>{{ page }}</a>
{% endif %}
{% endfor %}
<a href="/index3?p={{ next1 }}">下一页</a>
</body>
五 raw使用自定义sql语句分页查询
后台代码
from app0.models import m
def index4(req):
current_page_num = req.GET.get('p', None) # 当前页码
if not current_page_num:
current_page_num = 1
else:
current_page_num = int(current_page_num)
start = (current_page_num - 1) * 10 # 数据起始位置
info_num = 10 # 获取数据的数量
data_list = m.objects.raw("select * from app0_m limit %s,%s" % (start, info_num))
data_len = m.objects.all().count() # 全部数据数量
if current_page_num <= 1: # 上一页页码
after = current_page_num
else:
after = current_page_num - 1
if current_page_num >= data_len: # 下一页页码
next1 = current_page_num
else:
next1 = current_page_num + 1
return render(req, 'index4.html', locals())
前台代码
<body>
<ul>
{% for i in data_list %}
<li>{{ i.a }}</li>
{% endfor %}
</ul>
<a href="/index4?p={{ after }}">上一页</a>
{% for page in pages_list %}
{% if page == current_page_num %}
<a style="font-size: 30px" href=/index4?p={{ page }}>{{ page }}</a>
{% else %}
<a href=/index4?p={{ page }}>{{ page }}</a>
{% endif %}
{% endfor %}
<a href="/index4?p={{ next1 }}">下一页</a>
</body>
六 基于第四种方式的优化,减少数据库查询次数,但是一次要获取大量数据
后台代码
# 使用的第四种方法的自定义类
from app0.Paginator import my_Paginator as my_paginator
from django.views import View
class index5(View):
'''
为了减少数据库查询次数
故一次获取全部数据
只有从url获取不到页码时才会重新查询数据
为了保存查询到的数据才使用CBV的方式
'''
data = m.objects.all() # 获取全部数据
def get(self, req):
current_page_num = req.GET.get('p', None) # 当前页码
if not current_page_num:
self.data = m.objects.all()
current_page_num = 1
else:
current_page_num = int(current_page_num)
paginator = my_paginator(self.data, 10, 5, current_page_num) # 使用自定义分页组件实例对象
data_list = paginator.current_page_data_list # 当前页的数据
pages_list = paginator.page_num_range # 当前页的页码列表
after = paginator.previous_page # 上一页页码
next1 = paginator.next_page # 下一页页码
return render(req, 'index5.html', locals())
前台代码
<body>
<ul>
{% for i in data_list %}
<li>{{ i.a }}</li>
{% endfor %}
</ul>
<a href="/index5?p={{ after }}">上一页</a>
{% for page in pages_list %}
{% if page == current_page_num %}
<a style="font-size: 30px" href=/index5?p={{ page }}>{{ page }}</a>
{% else %}
<a href=/index5?p={{ page }}>{{ page }}</a>
{% endif %}
{% endfor %}
<a href="/index5?p={{ next1 }}">下一页</a>
</body>
七 基于第五种方式的分页优化,并对第四种方式的分页组件修改了一些
基于第四种方式自定义类修改后的类
class my_Paginator1:
'''
基于my_Paginator修改了一些功能
'''
def __init__(self, data_len, info_num_page, page_num):
self.data_len = data_len # 数据长度
self.info_num_page = info_num_page # 每页数据的数量
self.page_num = page_num # 每页分页下标数量
def start(self, current_page_num):
'''
返回当前页面数据开始位置、页码下标列表
:param current_page_num:
:return:
'''
temp = self.page_num // 2
if self.num_pages < self.page_num:
range_list = list(range(1, self.num_pages + 1))
elif temp >= current_page_num:
range_list = list(range(1, self.page_num + 1))
elif current_page_num >= self.num_pages - temp:
range_list = list(range(self.num_pages - self.page_num + 1, self.num_pages + 1))
else:
range_list = list(range(current_page_num - temp, current_page_num + temp + 1))
return self.info_num_page * (current_page_num - 1), range_list
@property
def num_pages(self):
'''
返回总页数
:return:
'''
a, b = divmod(self.data_len, self.info_num_page)
if b:
return a + 1
return a
@property
def last_page(self):
'''
返回最后一页页码
:return:
'''
return self.num_pages
后台代码
from app0.Paginator import my_Paginator1
class index6(View):
'''
为了减少每次从数据库查询到的数据量
故一次获取全部数据的数量
只有从url获取不到页码时才会重新查询数据数量
'''
data_len = m.objects.count() # 获取全部数据的条数
def get(self, req):
current_page_num = req.GET.get('p', None) # 当前页码
if not current_page_num:
self.data_len = m.objects.count()
current_page_num = 1
else:
current_page_num = int(current_page_num)
paginator = my_Paginator1(self.data_len, 10, 5) # 使用修改后的自定义分页组件实例化对象
start, pages_list = paginator.start(current_page_num) # 本页数据开始的位置、当前页的页码列表
data_list = m.objects.raw(
"select * from app0_m limit %s,%s" % (start, paginator.info_num_page)) # 当前页的数据
last = paginator.last_page # 最后一页页码
return render(req, 'index6.html', locals())
前台代码
<body>
<ul>
{% for i in data_list %}
<li>{{ i.a }}</li>
{% endfor %}
</ul>
<a href="/index6?p=1">第一页</a>
{% for page in pages_list %}
{% if page == current_page_num %}
<a style="font-size: 30px" href=/index6?p={{ page }}>{{ page }}</a>
{% else %}
<a href=/index6?p={{ page }}>{{ page }}</a>
{% endif %}
{% endfor %}
<a href="/index6?p={{ last }}">最后一页</a>
</body>