1,自定义分页
#utils文件夹下的page.py文件
class PagerHelper:
#total_count总的页数,current_page当前页数,base_url页面用来分页显示的URL如http://127.0.0.1:8000/classes.html/?p=71
#base_url为/calsses.html per_page每一页有多少条数据
def __init__(self,total_count,current_page,base_url,per_page=10):
self.total_count = total_count
self.current_page = current_page
self.base_url = base_url
self.per_page = per_page
@property
def db_start(self):
return (self.current_page -1) * self.per_page
@property
def db_end(self):
return self.current_page * self.per_page
#返回总的页数
def total_page(self):
v, a = divmod(self.total_count, self.per_page)
if a != 0:
v += 1
return v
#返回页码的HTML,默认是11页显示,小于11页时1-总页数,
#当前页小于6页时总显示1-11页,当前页加5(最后一页大于总页数时)显示(总页数-11,总页数)
def pager_str(self):
v = self.total_page()
pager_list = []
if self.current_page == 1:
pager_list.append('<a href="javascript:void(0);">上一页</a>')
else:
pager_list.append('<a href="%s?p=%s">上一页</a>' % (self.base_url, self.current_page - 1,))
# 6,1:12
# 7,2:13
if v <= 11:
pager_range_start = 1
pager_range_end = v
else:
if self.current_page < 6:
pager_range_start = 1
pager_range_end = 11 + 1
else:
pager_range_start = self.current_page - 5
pager_range_end = self.current_page + 5 + 1
if pager_range_end > v:
pager_range_start = v - 10
pager_range_end = v + 1
for i in range(pager_range_start, pager_range_end):
if i == self.current_page:
pager_list.append('<a class="active" href="%s?p=%s">%s</a>' % (self.base_url, i, i,))
else:
pager_list.append('<a href="%s?p=%s">%s</a>' % (self.base_url, i, i,))
if self.current_page == v:
pager_list.append('<a href="javascript:void(0);">下一页</a>')
else:
pager_list.append('<a href="%s?p=%s">下一页</a>' % (self.base_url, self.current_page + 1,))
pager = "".join(pager_list)
return pager
自定义分页
在函数中调用
#获取数据
total_count = 总的页数
current_page = 当前页数
'/classes.html' --> 当前分页的url
5 每一页显示数据,默认是10
######
from utils.page import PagerHelper
obj = PagerHelper(total_count, current_page, '/classes.html',5)
pager = obj.pager_str()
cls_list = models.Classes.objects.all()[obj.db_start:obj.db_end]
# current_user = request.session.get('username')
return render(request,
'classes.html',
{'username': current_user, 'cls_list': cls_list, 'str_pager': pager})
在views中使用
2,使用paginator和bootstrap实现分页
配置分页的接口
#在utilsde page.py中配置
from django.core.paginator import Paginator
from django.conf import settings
#接受两个参数
#request
#blogs_all_list所有的博客,Blog.objects.all()
def page_paginator(request,blogs_all_list):
paginator = Paginator(blogs_all_list, settings.EACH_PAGE_BLOGS_NUMBER)
# per_page: 每页显示条目数量
# count: 数据总个数
# num_pages:总页数
# page_range:总页数的索引范围,如: (1,10),(1,200)
# page: page对象
page_num = request.GET.get('page', 1) # 获取url的页面参数(GET请求)
page_of_blogs = paginator.get_page(page_num)
# has_next 是否有下一页
# next_page_number 下一页页码
# has_previous 是否有上一页
# previous_page_number 上一页页码
# object_list 分页之后的数据列表
# number 当前页
# paginator paginator对象
currentr_page_num = page_of_blogs.number # 获取当前页码
# 获取当前页码前后各2页的页码范围
page_range = list(range(max(currentr_page_num - 2, 1), currentr_page_num)) + \
list(range(currentr_page_num, min(currentr_page_num + 2, paginator.num_pages) + 1))
# 加上省略页码标记
if page_range[0] - 1 >= 2:
page_range.insert(0, '...')
if paginator.num_pages - page_range[-1] >= 2:
page_range.append('...')
# 加上首页和尾页
if page_range[0] != 1:
page_range.insert(0, 1)
if page_range[-1] != paginator.num_pages:
page_range.append(paginator.num_pages)
# 返回当前页的博客,和[首页,前2页,.....当前页,....,后两页,尾页]
return page_of_blogs,page_range
View Code
在views中调用接口
from utils.page import page_paginator
if request.method == 'GET':
blogs_all_list = models.Classes.objects.all()
page_of_blogs,page_range = page_paginator(request,blogs_all_list)
current_user = request.session.get('username')
return render(request,'classes.html', {'username':current_user,'blogs':page_of_blogs.object_list,'page_of_blogs':page_of_blogs,'page_range': page_range})
View Code
在模板中使用bootstrap
#在模板temolates中的layout.html中调用
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'base.css' %}">
<link rel="stylesheet" href="{% static 'bootstrap-3.3.7/css/bootstrap.min.css' %}">
<script type="text/javascript" src="{% static 'jquery-1.12.4.min.js' %}"></script>
<script type="text/javascript" src="{% static 'bootstrap-3.3.7/js/bootstrap.min.js' %}"></script>
<script type="text/javascript" src="{% static 'notifications/notify.js' %}"></script>
View Code
在setting中配置每一页显示的数据
EACH_PAGE_BLOGS_NUMBER = 10
在前端html中使用
<div class="paginator">
<ul class="pagination">
{# 上一页 #}
<li>
{% if page_of_blogs.has_previous %}
<a href="?p={{ page_of_blogs.previous_page_number }}" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
{% else %}
<span aria-hidden="true">«</span>
{% endif %}
</li>
{# 全部页码 #}
{% for page_num in page_range %}
{% if page_num == page_of_blogs.number %}
<li class="active"><span>{{ page_num }}</span></li>
{% else %}
{% if page_num == '...' %}
<li><span>{{ page_num }}</span></li>
{% else %}
<li><a href="?p={{ page_num }}">{{ page_num }}</a></li>
{% endif %}
{% endif %}
{% endfor %}
{# 下一页 #}
<li>
{% if page_of_blogs.has_next %}
<a href="?p={{ page_of_blogs.next_page_number }}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
{% else %}
<span aria-hidden="true">»</span>
{% endif %}
</li>
</ul>
<p>
共有{{ page_of_blogs.paginator.count }}篇博客,
当前第{{ page_of_blogs.number }}页,共{{ page_of_blogs.paginator.num_pages }}页
</p>
</div>
View Code
参考gitee的地址https://gitee.com/wuzhibin112423/python_paging_management.git
3、使用django的CBV模型实现分页
views中使用的是CBV,继承了ListView类
class IndexView(ListView):
model = Post
template_name = 'blog/index.html'
context_object_name = 'post_list'
# 指定 paginate_by 属性后开启分页功能,其值代表每一页包含多少篇文章
paginate_by = 10
#ListView默认给前端传递了以下的参数以供使用
#paginator ,即 Paginator 的实例。
#page_obj ,当前请求页面分页对象。
#is_paginated,是否已分页。只有当分页后页面超过两页时才算已分页。
#object_list,请求页面的对象列表,和 post_list 等价。所以在模板中循环文章列表时可以选 post_list ,也可以选 object_list。
views
templates/blog/index.html
{% if is_paginated %}
<div class="pagination-simple">
<!-- 如果当前页还有上一页,显示一个上一页的按钮 -->
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}">上一页</a>
{% endif %}
<!-- 显示当前页面信息 -->
<span class="current">第 {{ page_obj.number }} 页 / 共 {{ paginator.num_pages }} 页</span>
<!-- 如果当前页还有下一页,显示一个下一页的按钮 -->
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">下一页</a>
{% endif %}
</div>
{% endif %}
HTML
4、使用第三方的包:django-pure-pagination来实现分页
1、先安装应用
pip install django-pure-pagination
2,注册APP
INSTALLED_APPS = [
# ...
'pure_pagination', # 分页
'blog.apps.BlogConfig', # 注册 blog 应用
'comments.apps.CommentsConfig', # 注册 comments 应用
]
注册app
3.修改views
from pure_pagination import PaginationMixin
class IndexView(PaginationMixin, ListView):
model = Post
template_name = 'blog/index.html'
context_object_name = 'post_list'
paginate_by = 10
views
4、在settings配置分页
# django-pure-pagination 分页设置
PAGINATION_SETTINGS = {
'PAGE_RANGE_DISPLAYED': 4, # 分页条当前页前后应该显示的总页数(两边均匀分布,因此要设置为偶数),
'MARGIN_PAGES_DISPLAYED': 2, # 分页条开头和结尾显示的页数
'SHOW_FIRST_PAGE_WHEN_INVALID': True, # 当请求了不存在页,显示第一页
}
settings
5、在模板中使用
{% if is_paginated %}
{{ page_obj.render }}
{% endif %}
HTML
6、使用自定义模板覆盖预定义的模板
预定义的模板太丑,所以需要设置自定义的模板覆盖预定义的模板,django查找模板的顺序是首先在项目配置的模板根路径寻找,没有找到的话,
再去应用的templates目录下寻找。分页模板预定义的路径为 pure_pagination/pagination.html,所以我们可以在项目模板根路径下建立一个一模
一样的文件结构就可以覆盖。
/templates/pure_pagination/pagination.html
<div class="text-center pagination" style="width: 100%">
<ul>
{% if page_obj.has_previous %}
<li><a href="?{{ page_obj.previous_page_number.querystring }}"
class="prev">‹‹ </a></li>
{% else %}
<li><span class="disabled prev">‹‹ </span></li>
{% endif %}
{% for page in page_obj.pages %}
{% if page %}
{% ifequal page page_obj.number %}
<li class="current"><a href="#">{{ page }}</a></li>
{% else %}
<li><a href="?{{ page.querystring }}" class="page">{{ page }}</a></li>
{% endifequal %}
{% else %}
...
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li><a href="?{{ page_obj.next_page_number.querystring }}" class="next"> ››</a>
</li>
{% else %}
<li><span class="disabled next"> ››</span></li>
{% endif %}
</ul>
</div>
pagination.html