27-django 分页器

Django自带的分页器(paginator)

paginator分页器的使用

>>> from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(objects, 2) #2代表的是每页放多少数据
 
>>> p.count        #数据总数
4
>>> p.num_pages    #总页数
2
>>> type(p.page_range)  # `<type 'rangeiterator'>` in Python 2.
<class 'range_iterator'>
>>> p.page_range        #页码的列表
range(1, 3)     # =========[1,2]
 
>>> page1 = p.page(1)   #第1页的page对象
>>> page1
<Page 1 of 2>
>>> page1.object_list   #第1页的数据
['john', 'paul']
 
>>> page2 = p.page(2)
>>> page2.object_list    #第2页的数据
['george', 'ringo']
>>> page2.has_next()     #是否有下一页
False
>>> page2.has_previous() #是否有上一页
True
>>> page2.has_other_pages() #是否有其他页
True
>>> page2.next_page_number() #下一页的页码
Traceback (most recent call last):
...
EmptyPage: That page contains no results
>>> page2.previous_page_number()  #上一页的页码
1
>>> page2.start_index() # 本页第一条记录的序数(从1开始)
3
>>> page2.end_index() # 本页最后录一条记录的序数(从1开始)
4
 
>>> p.page(0)       #错误的页,抛出异常
Traceback (most recent call last):
...
EmptyPage: That page number is less than 1
>>> p.page(3)       #错误的页,抛出异常
Traceback (most recent call last):
...
EmptyPage: That page contains no results

实现一个分页效果demo:

Template:

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <link rel="stylesheet" href="{% static 'bootstrap.css' %}">

</head>
<body>


<div class="container">

    <h4>分页器</h4>
    <ul>

    {% for book in book_list %}
         <li>{{ book.title }} {{ book.price }}</li>
    {% endfor %}

</ul>


    <ul class="pagination" id="pager">

                 {% if book_list.has_previous %}
                    <li class="previous"><a href="/blog/?page={{ book_list.previous_page_number }}">上一页</a></li>
                 {% else %}
                    <li class="previous disabled"><a href="#">上一页</a></li>
                 {% endif %}


                 {% for num in paginator.page_range %}

                     {% if num == currentPage %}
                       <li class="item active"><a href="/blog/?page={{ num }}">{{ num }}</a></li>
                     {% else %}
                       <li class="item"><a href="/blog/?page={{ num }}">{{ num }}</a></li>

                     {% endif %}
                 {% endfor %}


                 {% if book_list.has_next %}
                    <li class="next"><a href="/blog/?page={{ book_list.next_page_number }}">下一页</a></li>
                 {% else %}
                    <li class="next disabled"><a href="#">下一页</a></li>
                 {% endif %}

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

views:

from django.shortcuts import render,HttpResponse

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

from app01.models import *
def index(request):

    '''
    批量导入数据:

    Booklist=[]
    for i in range(100):
        Booklist.append(Book(title="book"+str(i),price=30+i*i))
    Book.objects.bulk_create(Booklist)

    '''

    book_list=Book.objects.all()

    paginator = Paginator(book_list, 10)
    page = request.GET.get('page',1)
    currentPage=int(page)


    try:
        print(page)
        book_list = paginator.page(page)
    except PageNotAnInteger:
        book_list = paginator.page(1)
    except EmptyPage:
        book_list = paginator.page(paginator.num_pages)


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

改进版1:实现分页只保留固定的页数和被选中页高亮度显示

参考:Django之分页功能 

使用自定义标签:

pagetag.py

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# __author__ = "wuxiaoyu"
# Date: 2017/9/1
from django.utils.html import format_html
from django import template
register = template.Library()


@register.simple_tag()
def circle_page(current_page, loop_page):
    offset = abs(current_page - loop_page)
    if offset < 3:  # page页面与当前页面的差小于这个数的都会显示出来
        if current_page == loop_page:
            page_ele = '<li class="active"><a href="?page=%s">%s</a></li>' % (loop_page, loop_page)
        else:
            page_ele = '<li><a href="?page=%s">%s</a></li>' % (loop_page, loop_page)
        return format_html(page_ele)
    else:
        return ''

views.py

from django.shortcuts import render,HttpResponse,redirect
from app01.models import *
# Create your views here.
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

def index(request):
    '''
    Booklist = []
    for i in range(100):
        Booklist.append(Book(title="book" + str(i), price=30 + i * i))
    Book.objects.bulk_create(Booklist)
    :param reuest:
    :return:
    '''
    try:
        book_list=Book.objects.all()
        p=Paginator(book_list,5)
        page=request.GET.get("page")
        book_list=p.page(page)
    except PageNotAnInteger:
        book_list = p.page(1)
    except EmptyPage:
        book_list = p.page(p.num_pages)
    return render(request,"index.html",locals())


def login(request):
    if request.method=="POST":
        if 1:
            obj=HttpResponse("OK")
            obj.set_cookie("YYY222","2342342343",max_age=200)
            return obj
    return render(request,"login.html")

index.html

{% load pagetag %}
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <link rel="stylesheet" href="{% static 'dist/css/bootstrap.css'%}">
    <script src="{% static 'dist/js/jquery-3.2.1.min.js' %}"></script>
    <script src="{% static 'dist/js/bootstrap.js' %}"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-9 col-md-offset-3">
            <h4>分页</h4>
            <ul>
                {% for book in book_list %}
                  <li>{{ book.title }}&nbsp;&nbsp;{{ book.price }}</li>
                {% endfor %}
            </ul>

            <nav aria-label="Page navigation">
                  <ul class="pagination">
                      {% if book_list.has_previous %}
                      <li><a href="/index/?page={{ book_list.previous_page_number }}">上一页</a></li>
                       {% else %}
                          <li class="disabled"><a href="#">上一页</a></li>
                      {% endif %}

                      {% for num in p.page_range %}
                          {% circle_page book_list.number num %}
                      {% endfor %}
                       {% if book_list.has_next %}
                             <li><a href="/index/?page={{ book_list.next_page_number }}">下一页</a></li>
                       {% else %}
                              <li class="disabled"><a href="#">下一页</a></li>
                      {% endif %}
                  </ul>
            </nav>
        </div>
    </div>
</div>
</body>
</html>

效果:

缺点:翻到第一页的时候,页数有变化,如下

自定义分页终极版(*****重要~)

下面介绍一个通用的分页技巧,已封装好,只需要调用传参数即可。

 项目下新建目录utils,目录下新建文件 pagination.py

class Page(object):
    def __init__(self,current_page,all_count,base_url,per_page=10,pager_page_count=7):
        """
        分页初始化
        :param current_page: 当前页码
        :param per_page: 每页显示数据条数
        :param base_url: http://127.0.0.1:8000/index.html/?page=17# 中的/index.html/
        :param all_count: 数据库中总条数
        :param pager_page_count: 页面上最多显示的页码数量
        """
        self.base_url = base_url
        self.current_page = int(current_page)
        self.per_page = per_page
        self.all_count = all_count
        self.pager_page_count = pager_page_count
        pager_count, b = divmod(all_count, per_page)
        if b != 0:
            pager_count += 1
        self.pager_count = pager_count

        half_pager_page_count = int(pager_page_count / 2)
        self.half_pager_page_count = half_pager_page_count

    @property
    def start(self):
        """
        数据获取值起始索引
        :return:
        """
        return (self.current_page - 1) * self.per_page

    @property
    def end(self):
        """
        数据获取值结束索引
        :return:
        """
        return self.current_page * self.per_page

    def page_html(self):
        """
        生成HTML页码
        :return:
        """
        # 如果数据总页码pager_count<11 pager_page_count
        if self.pager_count < self.pager_page_count:
            pager_start = 1
            pager_end = self.pager_count
        else:
            # 数据页码已经超过11
            # 判断: 如果当前页 <= 5 half_pager_page_count
            if self.current_page <= self.half_pager_page_count:
                pager_start = 1
                pager_end = self.pager_page_count
            else:
                # 如果: 当前页+5 > 总页码
                if (self.current_page + self.half_pager_page_count) > self.pager_count:
                    pager_end = self.pager_count
                    pager_start = self.pager_count - self.pager_page_count + 1
                else:
                    pager_start = self.current_page - self.half_pager_page_count
                    pager_end = self.current_page + self.half_pager_page_count

        page_list = []
        if self.current_page <= 1:
            prev = '<li class="disabled"><a href="#">上一页</a></li>'
        else:
            prev = '<li><a href="%s?page=%s">上一页</a></li>' % (self.base_url,self.current_page - 1,)
        page_list.append(prev)
        for i in range(pager_start, pager_end + 1):
            if self.current_page == i:
                tpl = '<li><a class="active" href="%s?page=%s">%s</a></li>' % (self.base_url,i, i,)
            else:
                tpl = '<li><a href="%s?page=%s">%s</a></li>' % (self.base_url, i, i,)
            page_list.append(tpl)

        if self.current_page >= self.pager_count:
            nex = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            nex = '<li><a href="%s?page=%s">下一页</a></li>' % (self.base_url, self.current_page + 1,)
        page_list.append(nex)
        page_str = "".join(page_list)
        return page_str

urls.py

from django.conf.urls import url
from django.contrib import admin

from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
]

views.py

from utils.pagination import Page


def index(request):
    current_page = request.GET.get('page')
    all_count = models.Book.objects.all().count()
    # 默认参数:per_page=10,pager_page_count=7,pager_page_count最好是奇数,左右对称
    page_obj = Page(current_page, all_count, request.path_info, per_page=6, pager_page_count=7)
    book_list = models.Book.objects.all()[page_obj.start:page_obj.end]
    page_str = page_obj.page_html()

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

index.html 在需要页码的地方添加如下代码(配置好引用bootstrap和jquery)

 <ul class="pagination">
      {{ page_str|safe }}
 </ul>

如下示例:

{% load staticfiles %}

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

    <link rel="stylesheet" href="{% static 'dist/css/bootstrap.css'%}">
    <script src="{% static 'dist/js/jquery-3.2.1.min.js' %}"></script>
    <script src="{% static 'dist/js/bootstrap.js' %}"></script>
</head>
<body>
<div class="container">
    <table border="1">
        <thead>
            <tr>
                <th>ID</th>
                <th>title</th>
                <th>price</th>
            </tr>
        </thead>
        <tbody>
            {% for row in book_list %}
                <tr>
                    <td>{{ row.id }}</td>
                    <td>{{ row.title }}</td>  // 因为modles只定义了这两个字段
                    <td>{{ row.price }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
    <!--添加页码开始-->
    <ul class="pagination">
        {{ page_str|safe }}
    </ul>
    <!--添加页码结束-->
</div>

</body>
</html>

效果:

iview分页和后台数据交互

参考:

https://segmentfault.com/a/1190000010392169(这个是基于url不改变的)

http://www.cnblogs.com/landeanfen/p/6054654.html#_label3_9

https://juejin.im/entry/59ba71f76fb9a00a6974d86b(这个是基于url改变的)

posted @ 2017-08-27 18:13  番茄土豆西红柿  阅读(202)  评论(0)    收藏  举报
TOP