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})
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
在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})
在模板中使用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>
在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>
参考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。
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 %}
4、使用第三方的包:django-pure-pagination来实现分页
1、先安装应用
pip install django-pure-pagination
2,注册APP
INSTALLED_APPS = [ # ... 'pure_pagination', # 分页 'blog.apps.BlogConfig', # 注册 blog 应用 'comments.apps.CommentsConfig', # 注册 comments 应用 ]
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
4、在settings配置分页
# django-pure-pagination 分页设置 PAGINATION_SETTINGS = { 'PAGE_RANGE_DISPLAYED': 4, # 分页条当前页前后应该显示的总页数(两边均匀分布,因此要设置为偶数), 'MARGIN_PAGES_DISPLAYED': 2, # 分页条开头和结尾显示的页数 'SHOW_FIRST_PAGE_WHEN_INVALID': True, # 当请求了不存在页,显示第一页 }
5、在模板中使用
{% if is_paginated %}
{{ page_obj.render }}
{% endif %}
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>
人生苦短,我用cnblog