Django study notes (12) - Paging function

  This is a blog recording my notes in their own learning Django pagination. Paging function at each site are necessary, due to excessive need to show when the page data entry, leading to not show all this time you need to take the form of pagination on display.

  Paging can be seen everywhere on the site, the following shows a page style:

   Implement paging, not only to improve the user experience, but also reduce the pressure on the database to read data. Django comes with a tool called Paginator the page to help us implement paging function, this class is stored in django / core / paginator.py. It may receive a list of tuples or objects other iterations.

   The following first learn about the basic grammar of Paginator.

In Django Paginator basic grammar

1, the basic syntax of the pager functions Paginator

  Action Paginator our class is divided into a plurality of data paged parts, when we achieve a Paginator instance class, which need to pass parameters, we point to the Paginator class, see defined as follows:

class Paginator:

    def __init__(self, object_list, per_page, orphans=0,
                 allow_empty_first_page=True):
        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

  According to our definition can be explained as follows, (the above code is not posted their class attributes and methods):

  • object_list: may be a list, tuples, or other set of queries comprising count () or __len () method may __ slice objects. For continuous paging, inquiry should be ordered set, for example order_by item () or default ordering parameters.
  • per_page: each page contains the maximum number of entries, that does not include the page into separate pages.
  • orphans = 0: When you use this argument to show that you do not want the last page only a few entries. If the last page number of entries is less than a value equal to orphans, these entries will be merged into the previous (in this case becomes the last of the previous one). For example, 23 entries, per_page = 10, orphans = 0, by three, respectively 10,10,3, if orphans> = 3, compared with 2, respectively, 10, 13.
  • allow_empty_first_page = True: indicates the default allows the first page is blank

  Normally, we only need two arguments. The first argument is the data source, it may be a list, a tuple, and a query set. The second parameter need to pass an integer representing the number of data per page.

Class method Paginator

  • Paginator.page (number): return object based on a parameter Page number (number of multiples of 1)

Paginator class of property

  • Paginator.count: total number of pages for all objects that statistics object_list the item number when calculating the number of objects contained in object_list, Paginator will first try to call object_list.count (). If object_list not count () method, Paginator then rolled back using Len (object_list).
  • Paginator.num_pages: total number of pages
  • Paginator.page_range: page range, starting from 1 (regardless of the end list header Gu), for example, [1,2,3,4].

  The above three attributes are commonly used in our Paginator class property.

2, the basic syntax of the Page object

  We usually do not have to manually create a Page object, can be obtained from Paginator class. Paginator class provides a ** page (number) ** function, which returns a Page object. Parameter number represents the number of pages. If the number = 1, then the Page () Returns the object is a first tab of the Page object. The data displayed in the front page, our main operations are based on the Page object. Specific definitions are as follows:

class Page(collections.Sequence):

    def __init__(self, object_list, number, paginator):
        self.object_list = object_list
        self.number = number
        self.paginator = paginator

The method of page objects

  • Page. Has_next ()   if there is a next Returns True .
  • Page. Has_previous ()  if the previous page, returns  True .
  • Page. Has_other_pages ()  if there are previous or next page, return True .
  • Page. Next_page_number ()  Returns the next page number. If there is no next, throw InvlidPage exception.
  • Page. Previous_page_number ()  Return to the previous page number. If there is no previous thrown InvalidPage exception.
  • Page. Start_index ()  returns the first object on the current page, relative to the number of all objects in a list of pages, starting at 1. For example, a list of five objects into two objects per page, the second page of start_index () returns 3 .
  • Page. End_index ()  returns the last object on the current page, with page numbers for all objects of the list, starting at 1. For example, a list of five objects into two objects per page, the second page of end_index ()  will return  4 .

Property page object

  • Page. The object_list  list of all objects on the current page.
  • Page. Number The  current page number, starting at 1.
  • Page. Paginator  related Paginator objects

Usage page objects

  Below is an example:

# Paginator objects returned page object using the first page 

books = paginator.page (1)

  This is the time when the number = 1, page () Returns the object is a first tab Page object.

 

3, page numbers of illegal processing

  InvalidPage (Exception):  exception base class, is thrown paginator when passed an invalid page.

  Paginator.page () back when the requested page is invalid (for example, not an integer), or does not contain any objects throw an exception. Typically, the capture InvalidPage abnormal enough, but if you want more precise, you could capture one of the following two exceptions:

  • Exception  PageNotAnInteger , when the Page () throws providing a value not an integer.
  • Exception  EmptyPage , when the page () throws providing a valid value, but nothing on that page.

       The two exceptions are InalidPage subclass, it can simply the except  InvalidPage to handle them.

 

4, simple exercise of functions in class Paginator

Paging Web application is a common practice, Django provides a pager class Paginator (django.core.paginator.Paginator), can easily achieve paging function. 
This class has two constructors parameters, is a collection of data and the other is how much of each page of data release. 

Use Paginator substantially as follows: 

$ Python manage.py the shell 

>>> from django.core.paginator Import Paginator 

>>> Objects = [ 'John', 'Paul', 'George', 'Ringo'] 

>>> P = paginator (objects, 2) # page a pager two data 

>>> Number of data p.count # 

. 4 

>>> p.num_pages pages # 

2 

listing >>> p.page_range # page numbers 

[1, 2] 

>>> PAGE1 = p.page (1) # 1 page 

>>> PAGE1 

<page 1 of 2> 

>>> page1.object_list # 1 page data 

[ 'John', 'Paul'] 

>



>>> page2.has_next () # if there after a 

False 

>>> page2.has_previous () # if there are previous 

True 

>>> page2.has_other_pages () # if there are other pages 

True 

>>> page2.next_page_number () after a page number # 

3 

>>> page2.previous_page_number () before a page number # 

1 

ordinal >>> page2.start_index () # page first record (starting from 1) 

3 

>>> page2.end_index () # This page was last recorded a record number sequence (beginning from 1) 

4 

>>> p.page (0) # error page, an exception is thrown 

... EmptyPage: That iS page number the less Within last 1 

> >> p.page (3) # error page, an exception is thrown 

... EmptyPage: That page contains no results 


actually in front of scaffold-generated content which has already included the paging function, I believe that with the knowledge of Paginator, 
you and that they can understand how to use pager in view of the functions and templates.

  

5, a simple example of an application

from django.shortcuts import render,HttpResponse

# Create your views here.
from django.core.paginator import Paginator,InvalidPage,EmptyPage,PageNotAnInteger


def index(req):

    user_list=["用户"+str(i) for i in range(100)]

    user_list=getPage(req,user_list)

    return render(req,"index.html",locals())


def getPage(req,user_list):

    paginator=Paginator(user_list,5)

    try:
        current_page=req.GET.get("page",1) #  http://127.0.0.1:8000/index/?page=20
        article_list=paginator.page(current_page)
    except (EmptyPage,InvalidPage,PageNotAnInteger):
        article_list=paginator.page(1)

    return user_list


#*******----------index.html
{% for i in user_list %}
    <p>{{ i }}</p>
{% endfor %}

  

Production process pagination

1, the general idea of ​​complete pagination

The general idea of ​​learning the following page is divided into five steps.

  • 1, insert a lot of data to the database, and can ensure that tab
  • 2, complete a simple front-end pagination style, then we can see the prototype of paging
  • 3, complete digital page can click on to enter the function corresponding page
  • 4, complete Previous, Next to enter the function corresponding page
  • 5, if the total number of pages within a page beyond the default pages, we will be limited to 10

2, in order to prepare the data page

2.1, create a data model

  models.py code:

from django.db import models

# Create your models here.

class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(decimal_places=2, max_digits=8)

  The database synchronization.

2.2, add data to the database

  view view bulk import code data:

def index(request):
    # 批量导入
    book_list = []
    for i in range(100):
        book = Book(title='book_%s' %i, price=i*i)
        book_list.append(book)
    Book.objects.bulk_create(book_list)
    return HttpResponse("OK")
    

  In the above code, we inserted the 100 data, and the batch is present in the database.

  Book View database tables inside the data:

   After you have added the code will be commented out.

2.3, insert the back-end view of the data situation

  Here we use an ORM to get all the data in the database, and then use Paginator each page of data stored as 10, that is, the number of pieces of data per page is 10, where we can modify.

    = Book.objects.all book_list () 

    # Paginator tab requires two parameters 
    the paginator = Paginator (book_list, 10) 
    # Total Data 
    Print ( 'COUNT', paginator.count) 
    # total number of pages 
    print ( 'num_pages', paginator. NUM_PAGES) 
    # page list 
    print ( "page_range", paginator.page_range)

  The results are as follows:

count 100
num_pages 10
page_range range(1, 11)

  From the results, a total of 100 data, where a total of 10 pages of data, the page number for the list of [1,11]. (Because the list is care regardless of the end, so normal)

2.4, the case of the front page to show pagination

  Display the first page of two ways:

    # Two ways to show the data of the first page 
    PAGE1 paginator.page = (. 1) 
    Print (page1.object_list) 
    for I in PAGE1: 
        Print (I)

  View function to get the code of the current page:

    current_page = int(request.GET.get('page', 1))
    current_page = paginator.page(current_page)

  View renderings of the first page:

  Check the second page, or the page :( n only need to set up? Page = n can)

   However, if it exceeds the total number of pages, will be reported anomaly, or data from the page is a negative number (such as -1, -2, etc.), it is being given. Here we catch the exception in view view function:

    # If the page is greater than the total number of pages output, it can be captured with the unusually 
    the try: 
        current_page = int (request.GET.get ( 'Page',. 1)) 
        current_page = paginator.page (current_page) 
        # display a page specific data two ways 
        for I in current_page: 
            Print (I) 
    the except EmptyPage AS E: 
        current_page paginator.page = (. 1) 
    the except PageNotAnInteger: 
        current_page paginator.page = (. 1)

  Front-end code corresponding modification:

<ul>
    {% for book in current_page %}
        <li>{{ book.title }}:{{ book.price }}</li>
    {% endfor %}
</ul>

  

3,完善前端页面

  为了方便起见,我们使用了Bootstrap的CDN,这里我们直接使用Bootstrap里面的分页组件,进行简单的操作。

  下面是Bootstrap组件中一个简单的分页代码:

<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">«</span>
      </a>
    </li>
    <li><a href="#">1</a></li>
    <li><a href="#">2</a></li>
    <li><a href="#">3</a></li>
    <li><a href="#">4</a></li>
    <li><a href="#">5</a></li>
    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">»</span>
      </a>
    </li>
  </ul>
</nav>

  修改一下,代码如下:

<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">上一页</span>
      </a>
    </li>

      {% for foo in paginator.page_range %}
        <li><a href="#">{{ foo }}</a></li>
      {% endfor  %}

    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">下一页</span>
      </a>
    </li>
  </ul>
</nav>

  结果是这样的:

  虽然此时的效果已经完成,但是各个标签不能点击。下面我们继续完善。

4,点击1-10都进入对应的页面

  这时候,我们后端代码不需要改变,只需要修改前端代码即可。

  修改后的代码如下:

<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">上一页</span>
      </a>
    </li>

      {% for foo in paginator.page_range %}
      {% if current_page == foo%}
        <li><a class="active" href="?page={{ foo }}">{{ foo }}</a></li>
      {% else %}
        <li><a href="?page={{ foo }}">{{ foo }}</a></li>
      {% endif %}
      {% endfor  %}

    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">下一页</span>
      </a>
    </li>
  </ul>
</nav>

  这里我们点击每一页的时候,在href标签中动态的传输每一页的页码,这里就可以访问1-10中每一页的页面。

  注意:这里我们需要注意的是,当在url中输入 ?page=333的时候,也就是不存在的页码的时候,会报错,所以我们使用if - else 进行修改。如果不存在的时候就默认使用第一页即可。

  此时,我们点击1-10就可以进入对应的页面了,下面完成点击上一页,下一页进入对应的页面的功能。

5,点击上一页下一页进入对应的页面

  点击上一页,下一页进入对应的页面其实不难,但是需要注意的问题就是当上一页或者下一页没有数据的时候,我们需要进行处理。

  我们之前学过page对象的方法,在这里就可以使用。下面为了方便列出来需要用的:

  • Page.has_next():如果有下一页,则返回True。
  • Page.has_previous():如果有上一页,则返回True。
  • Page.next_page_number():返回下一页的页面。如果下一页不存在,抛出InvalidPage异常。
  • Page.previous_page_number():返回上一页的页面。如果上一页不存在,抛出InvalidPage异常

  下面修改前端代码,加入if-else判断:

<nav aria-label="Page navigation">
  <ul class="pagination">
  {% if current_page.has_previous %}
      <li><a href="?page={{ current_page.previous_page_number }}" aria-label="Previous">
          <span aria-hidden="true">上一页</span></a></li>
      {% else %}
      <li class="disabled"><a href="" aria-label="Next">
          <span aria-hidden="true">上一页</span></a></li>
      {% endif %}


      {% for foo in paginator.page_range %}
      {% if current_page_num == foo %}
        <li class="active"><a  href="?page={{ foo }}">{{ foo }}</a></li>
      {% else %}
        <li><a href="?page={{ foo }}">{{ foo }}</a></li>
      {% endif %}
      {% endfor  %}

      {% if current_page.has_next %}
      <li><a href="?page={{ current_page.next_page_number }}" aria-label="Next">
          <span aria-hidden="true">下一页</span></a></li>
      {% else %}
      <li class="disabled"><a href="" aria-label="Next">
          <span aria-hidden="true">下一页</span></a></li>
      {% endif %}
  </ul>
</nav>

  

6,如果一页内总页数超出默认页数,我们将其限制在10内

6.1 描述问题

  可能没有描述清楚,下面我们使用图和代码描述。  

  当每页显示3条数据的时候, view视图函数如下:

# Paginator 分页器需要两个参数
    paginator = Paginator(book_list, 3)

  前端代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

</head>
<body>

<ul>
    {% for book in current_page %}
        <li>{{ book.title }}-----------{{ book.price }}</li>
    {% endfor %}
</ul>




<nav aria-label="Page navigation">
  <ul class="pagination">
  {% if current_page.has_previous %}
      <li><a href="?page={{ current_page.previous_page_number }}" aria-label="Previous">
          <span aria-hidden="true">上一页</span></a></li>
      {% else %}
      <li class="disabled"><a href="" aria-label="Next">
          <span aria-hidden="true">上一页</span></a></li>
      {% endif %}


      {% for foo in paginator.page_range %}
      {% if current_page_num == foo %}
        <li class="active"><a  href="?page={{ foo }}">{{ foo }}</a></li>
      {% else %}
        <li><a href="?page={{ foo }}">{{ foo }}</a></li>
      {% endif %}
      {% endfor  %}

      {% if current_page.has_next %}
      <li><a href="?page={{ current_page.next_page_number }}" aria-label="Next">
          <span aria-hidden="true">下一页</span></a></li>
      {% else %}
      <li class="disabled"><a href="" aria-label="Next">
          <span aria-hidden="true">下一页</span></a></li>
      {% endif %}
  </ul>
</nav>

</body>
</html>

  所以效果如下:

6.2  修改并设置限定

  因为这样不好看,甚至说严重不好看,所以我们这里来将其限制到10内。

  在view视图函数中,我们可以判断num_page的大小,如果大于10,则设置范围,如果小于10,则正常即可。而大于10 的时候需要注意一个问题,那就是会出现-1或者大于页码范围的数,我们这里需要捕获,并将其修改。代码如下:

    current_page_num = int(request.GET.get('page', 1))

    if paginator.num_pages > 11:
        if current_page_num-5 < 1:
            page_range = range(1, 11)
        elif current_page_num + 5 > paginator.num_pages:
            page_range = range(paginator.num_pages-10, paginator.num_pages + 1)
        else:
            page_range = range(current_page_num-5, current_page_num+6)
    else:
       page_range = paginator.page_range

  前端只需要将Paginator.page_range修改为我们后端设置的page_range变量。

      {% for foo in page_range %}
      {% if current_page_num == foo %}
        <li class="active"><a  href="?page={{ foo }}">{{ foo }}</a></li>
      {% else %}
        <li><a href="?page={{ foo }}">{{ foo }}</a></li>
      {% endif %}
      {% endfor  %}

  这样得到的效果如下:

  即使他每页只显示3条数据,即使总页数很多,但是我们每页还是只显示10个页面。

 

7,完整的Django内置分页代码

7.1,Django内置分页

  views.py

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

L = []
for i in range(999):
    L.append(i)

def index(request):
    current_page = request.GET.get('p')

    paginator = Paginator(L, 10)
    # per_page: 每页显示条目数量
    # count:    数据总个数
    # num_pages:总页数
    # page_range:总页数的索引范围,如: (1,10),(1,200)
    # page:     page对象
    try:
        posts = paginator.page(current_page)
        # has_next              是否有下一页
        # next_page_number      下一页页码
        # has_previous          是否有上一页
        # previous_page_number  上一页页码
        # object_list           分页之后的数据列表
        # number                当前页
        # paginator             paginator对象
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)
    return render(request, 'index.html', {'posts': posts})

  

  html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<ul>
    {% for item in posts %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

<div class="pagination">
      <span class="step-links">
        {% if posts.has_previous %}
            <a href="?p={{ posts.previous_page_number }}">Previous</a>
        {% endif %}
          <span class="current">
            Page {{ posts.number }} of {{ posts.paginator.num_pages }}.
          </span>
          {% if posts.has_next %}
              <a href="?p={{ posts.next_page_number }}">Next</a>
          {% endif %}
      </span>

</div>
</body>
</html>

Html

  

7.2,扩展内置分页 

  views.py

from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger


class CustomPaginator(Paginator):
    def __init__(self, current_page, max_pager_num, *args, **kwargs):
        """
        :param current_page: 当前页
        :param max_pager_num:最多显示的页码个数
        :param args:
        :param kwargs:
        :return:
        """
        self.current_page = int(current_page)
        self.max_pager_num = max_pager_num
        super(CustomPaginator, self).__init__(*args, **kwargs)

    def page_num_range(self):
        # 当前页面
        # self.current_page
        # 总页数
        # self.num_pages
        # 最多显示的页码个数
        # self.max_pager_num
        print(1)
        if self.num_pages < self.max_pager_num:
            return range(1, self.num_pages + 1)
        print(2)
        part = int(self.max_pager_num / 2)
        if self.current_page - part < 1:
            return range(1, self.max_pager_num + 1)
        print(3)
        if self.current_page + part > self.num_pages:
            return range(self.num_pages + 1 - self.max_pager_num, self.num_pages + 1)
        print(4)
        return range(self.current_page - part, self.current_page + part + 1)


L = []
for i in range(999):
    L.append(i)

def index(request):
    current_page = request.GET.get('p')
    paginator = CustomPaginator(current_page, 11, L, 10)
    # per_page: 每页显示条目数量
    # count:    数据总个数
    # num_pages:总页数
    # page_range:总页数的索引范围,如: (1,10),(1,200)
    # page:     page对象
    try:
        posts = paginator.page(current_page)
        # has_next              是否有下一页
        # next_page_number      下一页页码
        # has_previous          是否有上一页
        # previous_page_number  上一页页码
        # object_list           分页之后的数据列表
        # number                当前页
        # paginator             paginator对象
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)

    return render(request, 'index.html', {'posts': posts})

扩展内置分页:views.py

  

  Html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<ul>
    {% for item in posts %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

<div class="pagination">
<span class="step-links">
{% if posts.has_previous %}
    <a href="?p={{ posts.previous_page_number }}">Previous</a>
{% endif %}

    {% for i in posts.paginator.page_num_range %}
        <a href="?p={{ i }}">{{ i }}</a>
    {% endfor %}

    {% if posts.has_next %}
        <a href="?p={{ posts.next_page_number }}">Next</a>
    {% endif %}
</span>

<span class="current">
Page {{ posts.number }} of {{ posts.paginator.num_pages }}.
</span>

</div>
</body>
</html>

扩展内置分页:Html

  

8、自定义分页

  分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。

  • 1、设定每页显示数据条数
  • 2、用户输入页码(第一页、第二页...)
  • 3、设定显示多少页号
  • 4、获取当前数据总条数
  • 5、根据设定显示多少页号和数据总条数计算出,总页数
  • 6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置
  • 7、在数据表中根据起始位置取值,页面上输出数据
  • 8、输出分页html,如:[上一页][1][2][3][4][5][下一页]

8.1  分页实例

#!/usr/bin/env python
# _*_coding:utf-8_*_
from django.utils.safestring import mark_safe
 
class PageInfo(object):
    def __init__(self,current,totalItem,peritems=5):
        self.__current=current
        self.__peritems=peritems
        self.__totalItem=totalItem
    def From(self):
        return (self.__current-1)*self.__peritems
    def To(self):
        return self.__current*self.__peritems
    def TotalPage(self):  #总页数
        result=divmod(self.__totalItem,self.__peritems)
        if result[1]==0:
            return result[0]
        else:
            return result[0]+1
 
def Custompager(baseurl,currentPage,totalpage):  #基础页,当前页,总页数
    perPager=11
    #总页数<11
    #0 -- totalpage
    #总页数>11
        #当前页大于5 currentPage-5 -- currentPage+5
            #currentPage+5是否超过总页数,超过总页数,end就是总页数
        #当前页小于5 0 -- 11
    begin=0
    end=0
    if totalpage <= 11:
        begin=0
        end=totalpage
    else:
        if currentPage>5:
            begin=currentPage-5
            end=currentPage+5
            if end > totalpage:
                end=totalpage
        else:
            begin=0
            end=11
    pager_list=[]
    if currentPage<=1:
        first="<a href=''>首页</a>"
    else:
        first="<a href='%s%d'>首页</a>" % (baseurl,1)
    pager_list.append(first)
 
    if currentPage<=1:
        prev="<a href=''>上一页</a>"
    else:
        prev="<a href='%s%d'>上一页</a>" % (baseurl,currentPage-1)
    pager_list.append(prev)
 
    for i in range(begin+1,end+1):
        if i == currentPage:
            temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i)
        else:
            temp="<a href='%s%d'>%d</a>" % (baseurl,i,i)
        pager_list.append(temp)
    if currentPage>=totalpage:
        next="<a href='#'>下一页</a>"
    else:
        next="<a href='%s%d'>下一页</a>" % (baseurl,currentPage+1)
    pager_list.append(next)
    if currentPage>=totalpage:
        last="<a href=''>末页</a>"
    else:
        last="<a href='%s%d'>末页</a>" % (baseurl,totalpage)
    pager_list.append(last)
    result=''.join(pager_list)
    return mark_safe(result)   #把字符串转成html语言

  总结,分页时需要做三件事:

  • 创建处理分页数据的类
  • 根据分页数据获取数据
  • 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]

 

9,自定义分页的实例

from django.shortcuts import render,HttpResponse

# Create your views here.
from django.core.paginator import Paginator,InvalidPage,EmptyPage,PageNotAnInteger


def index(req):

    user_list_all=["用户"+str(i) for i in range(1000)]
    #需要分页显示

    current_page=int(req.GET.get("page",1))

    # start=(current_page-1)*5
    # end=(current_page-1)*5+5
    start=(current_page-1)*10
    end=(current_page-1)*10+10

    user_list=user_list_all[start:end]
    #不能让用户去url写page,所以写入Page Number
    #问题是:显示多少页码(Page Number)?

    total_item=len(user_list_all)
    pageNumber,remaining=divmod(total_item,10)  #每页显示10条数据
    if remaining>0:
        pageNumber+=1

    list_tag=[]

    #默认最多显示10页码
    PN=6
    half_PN=int(PN/2)
    if pageNumber<PN:
        BEGIN=0
        END=pageNumber
    else:
        if current_page>half_PN:

            if current_page<(pageNumber-half_PN):
                BEGIN=current_page-half_PN
                END=current_page+half_PN
            else:
                #最后几页不需要再增加新的页码
                BEGIN=pageNumber-PN
                END=pageNumber
        else:
            BEGIN=0
            END=PN

    baseurl='/index/?page='

    if current_page<=1:
        first="<a href='#'>首页</a>"
    else:
        first="<a href='%s%d'>首页</a>" % (baseurl,1)
    list_tag.append(first)

    if current_page<=1:
        prev="<a href=''>上一页</a>"
    else:
        prev="<a href='%s%d'>上一页</a>" % (baseurl,current_page-1)
    list_tag.append(prev)

    for i in range(BEGIN+1,END+1):
        if i == current_page:
            temp="<a href='%s%d' class='active'>%d</a>" % (baseurl,i,i)
        else:
            temp="<a href='%s%d'>%d</a>" % (baseurl,i,i)
        list_tag.append(temp)
    if current_page>=pageNumber:
        next="<a href='#'>下一页</a>"
    else:
        next="<a href='%s%d'>下一页</a>" % (baseurl,current_page+1)
    list_tag.append(next)
    if current_page>=pageNumber:
        last="<a href='#'>末页</a>"
    else:
        last="<a href='%s%d'>末页</a>" % (baseurl,pageNumber)

    list_tag.append(last)

    tags="".join(list_tag)

    return render(req,"index.html",locals())



#------------------------------------index.html
#------------------------------------

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .pager a{
            display: inline-block;
            width: 60px;
            height: 20px;
            padding: 5px;
            background-color: darkgrey;
            color: #2459a2;
            text-decoration: none;
            text-align: center;
            line-height: 20px;
        }
        .pager a.active{
            color: white;
            background-color: red;
        }
    </style>
</head>
<body>


{% for user in user_list %}
    <p>{{ user }}</p>
{% endfor %}
<div class="pager">
    {{ tags|safe }}
</div>

</body>
</html>

  

参考文献:https://www.cnblogs.com/king-lps/p/7324821.html

Guess you like

Origin www.cnblogs.com/wj-1314/p/10620178.html