Django
提供了一个新的类来帮助你管理分页数据,这个模块存放在django.core.paginator.py
。其中有两个核心类,一个是Paginator
类,另一个是Page
类。
Paginator
类1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Paginator : def __init__ (self, object_list, per_page, orphans=0 ,allow_empty_first_page=True ): ''' 初始化操作 :param object_list:可以是列表,元组,查询集或其他含有 count() 或 len()方法的可切片对象。对于连续的分页,查询集应该有序,例如有order_by()项或默认ordering参数。 :param per_page:每一页中包含条目数目的最大值,不包括独立成页的那页。(见下面 orphans参数解释)。 :param orphans:当你使用此参数时说明你不希望最后一页只有很少的条目。如果最后一页的条目数少于等于orphans的值,则这些条目会被归并到上一页中(此时的上一页变为最后一页)。 :param allow_empty_first_page:默认允许第一页为空。 ''' self.object_list = object_list self._check_object_list_is_ordered() self.per_page = int (per_page) self.orphans = int (orphans) self.allow_empty_first_page = allow_empty_first_page
类属性 Paginator.count
:所有页面对象总数,即统计object_list
中item
数目。 当计算object_list
所含对象的数量时, Paginator
会首先尝试调用object_list.count()
。 如果object_list
没有 count() 方法
,Paginator
接着会回退使用len(object_list)
。Pagnator.num_pages
:页面总数。pagiator.page_range
:页面范围,从1开始,例如[1,2,3,4]。类方法 Paginator.page(number)
:根据参数number
返回一个Page
对象。(number
为1的倍数)即:下面的Page
类对象 Page
类1 2 3 4 5 6 7 8 9 10 11 12 class Page (collections.abc.Sequence ): def __init__ (self, object_list, number, paginator ): ''' 初始化 :param object_list:当前页上所有对象的列表。 :param number:当前页的序号,从1开始。 :param paginator:相关的Paginator对象。 ''' self.object_list = object_list self.number = number self.paginator = paginator
类方法 Page.has_next()
如果有下一页,则返回True
。Page.has_previous()
如果有上一页,返回 True
。Page.has_other_pages()
如果有上一页或下一页,返回True
。Page.next_page_number()
返回下一页的页码。如果下一页不存在,抛出InvlidPage
异常。Page.previous_page_number()
返回上一页的页码。如果上一页不存在,抛出InvalidPage
异常。Page.start_index()
返回当前页上的第一个对象,相对于分页列表的所有对象的序号,从1开始。 比如,将五个对象的列表分为每页两个对象,第二页的start_index()
会返回3。Page.end_index()
返回当前页上的最后一个对象,相对于分页列表的所有对象的序号,从1开始。 比如,将五个对象的列表分为每页两个对象,第二页的end_index()
会返回 4。异常处理 InvalidPage(Exception)
: 异常的基类,当paginator
传入一个无效的页码时抛出。Paginator.page()
放回在所请求的页面无效(比如不是一个整数)时,或者不包含任何对象时抛出异常。通常,捕获InvalidPage
异常就够了,但是如果你想更加精细一些,可以捕获以下两个异常之一:exception PageNotAnInteger
,当向page()
提供一个不是整数的值时抛出。exception EmptyPage
,当向page()
提供一个有效值,但是那个页面上没有任何对象时抛出。 这两个异常都是InalidPage
的子类,所以可以通过简单的except InvalidPage
来处理它们。示例 视图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 from django.shortcuts import renderfrom django.core.paginator import Paginator, EmptyPage, PageNotAnIntegerfrom .models import Articledef index (request ): articles = Article.objects.all () pageinator = Paginator(articles, 4 ) page = request.GET.get('page' ) try : article_datas = pageinator.page(page) except PageNotAnInteger: article_datas = pageinator.page(1 ) except EmptyPage: article_datas = pageinator.page(pageinator.num_pages) return render(request, 'index.html' , {'articles' :article_datas})
模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <html lang ="en" > <head > <meta charset ="UTF-8" > <meta name ="viewport" content ="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" > <meta http-equiv ="X-UA-Compatible" content ="ie=edge" > <title > Document</title > </head > <body > <ul > {% for arc in articles %} <li > {{ arc.title }}</li > {% endfor %} </ul > {% if articles.has_previous %} <a href ="?page={{ articles.previous_page_number }}" > 上一页</a > {% endif %} <em > 页码:{{ articles.number }} of {{ articles.paginator.num_pages }}</em > {% if articles.has_next %} <a href ="?page={{ articles.next_page_number }}" > 下一页</a > {% endif %} </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 from django.shortcuts import renderfrom django.core.paginator import Paginator, EmptyPage, PageNotAnIntegerfrom .models import Articledef index (request ): articles = Article.objects.all () pageinator = Paginator(articles, 4 ) page = request.GET.get('page' ) try : article_datas = pageinator.page(page) except PageNotAnInteger: article_datas = pageinator.page(1 ) except EmptyPage: article_datas = pageinator.page(pageinator.num_pages) return render(request, 'index.html' , {'articles' :article_datas, 'page_code' :pageinator.page_range})
模板 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 <html lang ="en" > <head > <meta charset ="UTF-8" > <meta name ="viewport" content ="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" > <meta http-equiv ="X-UA-Compatible" content ="ie=edge" > <title > Document</title > </head > <body > <ul > {% for arc in articles %} <li > {{ arc.title }}</li > {% endfor %} </ul > {% if articles.has_previous %} <a href ="?page={{ articles.previous_page_number }}" > 上一页</a > {% endif %} <div > {% for num in page_code %} <a href ="?page={{ num }}" {% if num == articles.number %} style ="color: red" {% endif %}> {{ num }}</a > {% endfor %} </div > <em > 页码:{{ articles.number }} of {{ articles.paginator.num_pages }}</em > {% if articles.has_next %} <a href ="?page={{ articles.next_page_number }}" > 下一页</a > {% endif %} </body > </html >
效果 我们加上了页码,并高亮了当前页码。
扩展 我们当前文章较少,如果数量较多,如果页码达到100页,我们不可能将100个页码都显示在页面上,我们想要像百度一样,只显示10个页码,当前页码左右各5个要怎么做呢?我们数据量较少,我们这里只显示5个页码。
视图 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 django.core.paginator import Paginator, EmptyPage, PageNotAnIntegerfrom .models import Articledef index (request ): articles = Article.objects.all () pageinator = Paginator(articles, 3 ) page = request.GET.get('page' ) try : article_datas = pageinator.page(page) page = int (page) except PageNotAnInteger: article_datas = pageinator.page(1 ) page = 1 except EmptyPage: article_datas = pageinator.page(pageinator.num_pages) page = pageinator.num_pages if pageinator.num_pages>10 : if page-2 <1 : page_codes = range (1 , 6 ) elif page+2 > pageinator.num_pages: page_codes = range (pageinator.num_pages-4 , pageinator.num_pages+1 ) else : page_codes = range (page-2 , page+3 ) else : page_codes = pageinator.page_range return render(request, 'index.html' , {'articles' :article_datas, 'page_code' :page_codes})
模板 模板跟上面没有任何变化
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 <html lang ="en" > <head > <meta charset ="UTF-8" > <meta name ="viewport" content ="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" > <meta http-equiv ="X-UA-Compatible" content ="ie=edge" > <title > Document</title > </head > <body > <ul > {% for arc in articles %} <li > {{ arc.title }}</li > {% endfor %} </ul > {% if articles.has_previous %} <a href ="?page={{ articles.previous_page_number }}" > 上一页</a > {% endif %} <div > {% for num in page_code %} <a href ="?page={{ num }}" {% if num == articles.number %} style ="color: red" {% endif %}> {{ num }}</a > {% endfor %} </div > <em > 页码:{{ articles.number }} of {{ articles.paginator.num_pages }}</em > {% if articles.has_next %} <a href ="?page={{ articles.next_page_number }}" > 下一页</a > {% endif %} </body > </html >
效果