Django_分页

目录

基本语法

示例

 

 

简介

Django提供了一个新的类来帮助你管理分页数据,这个类存放在django/core/paginator.py.它可以接收列表、元组或其它可迭代的对象。

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

    def validate_number(self, number):
        """Validate the given 1-based page number."""
        try:
            number = int(number)
        except (TypeError, ValueError):
            raise PageNotAnInteger(_('That page number is not an integer'))
        if number < 1:
            raise EmptyPage(_('That page number is less than 1'))
        if number > self.num_pages:
            if number == 1 and self.allow_empty_first_page:
                pass
            else:
                raise EmptyPage(_('That page contains no results'))
        return number

    def get_page(self, number):
        """
        Return a valid page, even if the page argument isn't a number or isn't
        in range.
        """
        try:
            number = self.validate_number(number)
        except PageNotAnInteger:
            number = 1
        except EmptyPage:
            number = self.num_pages
        return self.page(number)

    def page(self, number):
        """Return a Page object for the given 1-based page number."""
        number = self.validate_number(number)
        bottom = (number - 1) * self.per_page
        top = bottom + self.per_page
        if top + self.orphans >= self.count:
            top = self.count
        return self._get_page(self.object_list[bottom:top], number, self)

    def _get_page(self, *args, **kwargs):
        """
        Return an instance of a single page.

        This hook can be used by subclasses to use an alternative to the
        standard :cls:`Page` object.
        """
        return Page(*args, **kwargs)

    @cached_property
    def count(self):
        """Return the total number of objects, across all pages."""
        try:
            return self.object_list.count()
        except (AttributeError, TypeError):
            # AttributeError if object_list has no count() method.
            # TypeError if object_list.count() requires arguments
            # (i.e. is of type list).
            return len(self.object_list)

    @cached_property
    def num_pages(self):
        """Return the total number of pages."""
        if self.count == 0 and not self.allow_empty_first_page:
            return 0
        hits = max(1, self.count - self.orphans)
        return int(ceil(hits / float(self.per_page)))

    @property
    def page_range(self):
        """
        Return a 1-based range of pages for iterating through within
        a template for loop.
        """
        return range(1, self.num_pages + 1)

    def _check_object_list_is_ordered(self):
        """
        Warn if self.object_list is unordered (typically a QuerySet).
        """
        ordered = getattr(self.object_list, 'ordered', None)
        if ordered is not None and not ordered:
            obj_list_repr = (
                '{} {}'.format(self.object_list.model, self.object_list.__class__.__name__)
                if hasattr(self.object_list, 'model')
                else '{!r}'.format(self.object_list)
            )
            warnings.warn(
                'Pagination may yield inconsistent results with an unordered '
                'object_list: {}.'.format(obj_list_repr),
                UnorderedObjectListWarning,
                stacklevel=3
            )
django.core.paginator源码

基本语法

# -*- coding:utf-8 -*-
from django.core.paginator import Paginator

objects = ['john', 'paul', 'george', 'ringo', 'lucy', 'meiry', 'checy', 'wind', 'flow', 'rain']
p = Paginator(objects, 3)  # 3条数据为一页,实例化分页对象
print(p.count)  # 10 对象总共10个元素
print(p.num_pages)  # 4 对象可分4页
print(p.page_range)  # range(1, 5) 对象页的可迭代范围

page1 = p.page(1)  # 取对象的第一分页对象
print(page1.object_list)  # 第一分页对象的元素列表['john', 'paul', 'george']
print(page1.number)  # 第一分页对象的当前页值 1

page2 = p.page(2)  # 取对象的第二分页对象
print(page2.object_list)  # 第二分页对象的元素列表 ['ringo', 'lucy', 'meiry']
print(page2.number)  # 第二分页对象的当前页码值 2

print(page1.has_previous())  # 第一分页对象是否有前一页 False
print(page1.has_other_pages())  # 第一分页对象是否有其它页 True

print(page2.has_previous())  # 第二分页对象是否有前一页 True
print(page2.has_next())  # 第二分页对象是否有下一页 True
print(page2.next_page_number())  # 第二分页对象下一页码的值 3
print(page2.previous_page_number())  # 第二分页对象的上一页码值 1
print(page2.start_index())  # 第二分页对象的元素开始索引 4
print(page2.end_index())  # 第2分页对象的元素结束索引 6

 

示例

示例1 使用django内置Paginator模块

from django.urls import path,re_path,include
from testpaginator import views

urlpatterns = [
    re_path("index/",views.Index.as_view()),
]
urls.py
from django.db import models


class Product(models.Model):
    name = models.CharField(max_length=64)
    price = models.IntegerField()

    def __str__(self):
        return "{}-{}".format(self.name,self.price)
models.py
from django.shortcuts import render
from django.views import View
from . import models
from django.core.paginator import Paginator,PageNotAnInteger,EmptyPage
class Index(View):
    def get(self,request):
        product_obj_list = models.Product.objects.all()

        paginator = Paginator(product_obj_list,10)
        page = request.GET.get("page")

        try:
            product_obj_list_new = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            product_obj_list_new = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            product_obj_list_new = paginator.page(paginator.num_pages)


        context = {
            "product_obj_list":product_obj_list_new
        }

        return render(request,"page.html",context)
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ol>
        {% for product_obj in product_obj_list %}
            {# Each "contact" is a Contact model object. #}
            <li>{{ product_obj }}</li>
        {% endfor %}
    </ol>


    <div class="pagination">
        <span class="step-links">
            {% if product_obj_list.has_previous %}
                <a href="?page={{ product_obj_list.previous_page_number }}">previous</a>
            {% endif %}

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

            {% if product_obj_list.has_next %}
                <a href="?page={{ product_obj_list.next_page_number }}">next</a>
            {% endif %}
        </span>
    </div>



</body>
</html>
page.html

示例2 改写Paginator

# -*- coding:utf-8 -*-
from django.core.paginator import Paginator

class CustomPaginator(Paginator):
    # 使用方法paginator = CustomPaginator(current_page,per_pager_num,obj_list,per_page)
    # current_page :: 当前页面
    # per_pager_num :: 显示多少个页码
    # obj_list :: 对象列表,显示的主体
    # per_page :: 每页多少条目

    def __init__(self, current_page, per_pager_num, *args, **kwargs):
        # per_pager_num  显示的页码数量
        self.current_page = int(current_page)
        self.per_pager_num = int(per_pager_num)
        super(CustomPaginator, self).__init__(*args, **kwargs)

    def pager_num_range(self):
        '''
        自定义显示页码数
        第一种:总页数小于显示的页码数
        第二种:总页数大于显示页数  根据当前页做判断  a 如果当前页大于显示页一半的时候  ,往右移一下
                                                b 如果当前页小于显示页的一半的时候,显示当前的页码数量
        第三种:当前页大于总页数
        :return:
        '''

        # 第一种:总页数小于显示的页码数
        if self.num_pages < self.per_pager_num:

            # 如果总页数只有10页,而设置了显示20个页码,则按照总页数显示
            return range(1, self.num_pages + 1)

        # 第二种:总页数大于显示页数  根据当前页做判断
        half_part = int(self.per_pager_num / 2)
        # a 如果当前页大于显示页一半的时候  ,往右移一下
        if self.current_page <= half_part:
            # 当前页小于显示页码数量的一半时,比如当前页是3,显示20个页码,则显示1-20这些页码
            return range(1, self.per_pager_num + 1)
        # b 如果当前页小于显示页的一半的时候,显示当前的页码数量
        if (self.current_page + half_part) > self.num_pages:
            # 当前页大于显示页码数量的一半时,比如当前页是13,显示20个页码,则显示13-10=3 到 13+10=23的这3-23的页码
            return range(self.num_pages - self.per_pager_num + 1, self.num_pages + 1)

        # 第三种:当前页大于总页数,配合EmptyPage使用,则显示最后一页及其往前20个页码
        return range(self.current_page - half_part, self.current_page + half_part + 1)
pager.py
from django.shortcuts import render
from django.views import View
from . import models
from .utils.pager import CustomPaginator
from django.core.paginator import PageNotAnInteger,EmptyPage

class Index(View):
    def get(self,request):
        product_obj_list = models.Product.objects.all()
        page = request.GET.get("page")
        paginator = CustomPaginator(page,20,product_obj_list,10)


        try:
            product_obj_list_new = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            product_obj_list_new = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            product_obj_list_new = paginator.page(paginator.num_pages)


        context = {
            "product_obj_list":product_obj_list_new
        }

        return render(request,"page.html",context)
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>



    <ol>
        {% for product_obj in product_obj_list %}
{#             Each "contact" is a Contact model object.#}
            <li>{{ product_obj }}</li>
        {% endfor %}
    </ol>


    <div class="pagination">
        <span class="step-links">
            {% if product_obj_list.has_previous %}
                <a href="?page={{ product_obj_list.previous_page_number }}">previous</a>
            {% endif %}

            {% for number in product_obj_list.paginator.pager_num_range %}
                {% if number == product_obj_list.number %}
                    <a href="?page={{ number }}" style="font-size: 33px">{{ number }}</a>
                {% else %}
                    <a href="?page={{ number }}" >{{ number }}</a>
                {% endif %}

            {% endfor %}

            {% if product_obj_list.has_next %}
                <a href="?page={{ product_obj_list.next_page_number }}">next</a>
            {% endif %}
            <span>({{ product_obj_list.number }}/{{ product_obj_list.paginator.num_pages }})</span>
        </span>
    </div>



</body>
</html>
page.html

示例3 自定义pager组件

示例3.1 objs与pager各自单独使用

class PageInfo(object):
    def __init__(self,current_page,all_count,base_url,per_page=10,max_show_page=11):

        self.per_page = per_page
        self.all_count = all_count
        self._current_page = current_page
        self.max_show_page = max_show_page
        self.base_url = base_url


    @property
    def actual_current_page(self):
        """
        涉及到(<=0,<0<=all_page,>all_page)
        :return:
        """
        try:
            current_page = int(self._current_page)
            if current_page > self.all_page:
                current_page = self.all_page
            elif current_page <= 0:
                current_page = 1

        except Exception as e:
            current_page = 1
        return current_page

    @property
    def all_page(self):
        all_page, plus = divmod(self.all_count, self.per_page)
        if plus:
            all_page += 1
        return all_page


    @property
    def start(self):
        return (self.actual_current_page-1) * self.per_page

    @property
    def end(self):
        return self.actual_current_page * self.per_page

    @property
    def pager_range(self):
        """
        显示的页码范围
        :return: (begin,stop)
        """
        half = (self.max_show_page) // 2
        # 如果数据总页数 < 11
        if self.all_page < self.max_show_page:
            begin = 1
            stop = self.all_page + 1
        # 如果数据总页数 > 11
        else:
            # 如果当前页 <= 5,永远显示1,11
            if self.actual_current_page <= half:

                begin = 1
                stop = self.max_show_page + 1
            else:
                if self.actual_current_page + half > self.all_page:
                    # begin = self.actual_current_page - half
                    begin = self.all_page - self.max_show_page + 1
                    stop = self.all_page + 1
                else:
                    begin = self.actual_current_page - half
                    stop = self.actual_current_page + half + 1

        return (begin,stop)



    def pager_str(self):
        # v = '<a href="/custom.html?page=1">1</a>'
        # return v
        page_list = []
        begin, stop = self.pager_range

        # 上一页按钮
        if self.actual_current_page <= 1:
            prev = '<li><a href="#">上一页</a></li>'
        else:
            prev = '<li><a href="{}?page={}">上一页</a></li>'.format(self.base_url,self.actual_current_page-1)
        page_list.append(prev)

        # 页码按钮
        for i in range(begin,stop):
            if i == self.actual_current_page:
                tmp = '<li class="active"><a href="{}?page={}">{}</a></li>'.format(self.base_url,i,i)
            else:
                tmp = '<li><a href="{}?page={}">{}</a></li>'.format(self.base_url,i,i)
            page_list.append(tmp)

        # if self.actual_current_page >= self.all_pager:
        #     after = '<li><a href="#">下一页</a></li>'
        # else:
        #     after = '<li><a href="{}?page={}">下一页</a></li>'.format(self.base_url,self.actual_current_page+1)
        # page_list.append(after)

        # 下一页按钮
        if self.actual_current_page >= self.all_page:
            after = '<li><a href="#">下一页</a></li><span>({start}-{end}/共{total})</span>'.format(
                start=self.start+1 if self.start<self.all_count else self.all_count,
                end=self.end if self.end<self.all_count else self.all_count,
                total=self.all_count)
        else:
            after = '<li><a href="{url}?page={next_page}">下一页</a></li><span>({start}-{end}/共{total})</span>'.format(
                url=self.base_url,
                next_page=self.actual_current_page+1,
                start=self.start+1 if self.start<self.all_count else self.all_count,
                end=self.end if self.end<self.all_count else self.all_count,
                total=self.all_count
            )
        page_list.append(after)

        return " ".join(page_list)
pager2.py
from .utils.pager2 import PageInfo
from django.shortcuts import render
from django.views import View
from . import models

class Index(View):
    def get(self,request):
        page = request.GET.get("page")
        product_obj_list = models.Product.objects.all()
        all_count = product_obj_list.count()

        page_info = PageInfo(page,all_count,"")

        product_obj_list_new = product_obj_list[page_info.start:page_info.end]

        context = {
            "product_obj_list":product_obj_list_new,
            "pager":page_info,
        }

        return render(request,"page.html",context)
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.5-dist/css/bootstrap.min.css">
</head>
<body>



    <ol>
        {% for product_obj in product_obj_list %}
{#             Each "contact" is a Contact model object.#}
            <li>{{ product_obj }}</li>
        {% endfor %}
    </ol>
    <nav aria-label="Page navigation">
        <ul class="pagination">
        {{ pager.pager_str|safe }}
        </ul>
    </nav>
    {{ pager.pager_str|safe }}

</body>
</html>
page.html

示例3.2 objs封装到pager里

# -*- coding:utf-8 -*-

class PageInfo(object):
    def __init__(self,items,current_page,base_url,per_page=10,max_show_page=11):
        self._items = items
        self.per_page = per_page
        self.all_count = self._items.count()
        self._current_page = current_page
        self.max_show_page = max_show_page
        self.base_url = base_url


    @property
    def items(self):
        return self._items[self.start:self.end]


    @property
    def actual_current_page(self):
        """
        涉及到(<=0,<0<=all_page,>all_page)
        :return:
        """
        try:
            current_page = int(self._current_page)
            if current_page > self.all_page:
                current_page = self.all_page
            elif current_page <= 0:
                current_page = 1

        except Exception as e:
            current_page = 1
        return current_page

    @property
    def all_page(self):
        all_page, plus = divmod(self.all_count, self.per_page)
        if plus:
            all_page += 1
        return all_page


    @property
    def start(self):
        return (self.actual_current_page-1) * self.per_page

    @property
    def end(self):
        return self.actual_current_page * self.per_page

    @property
    def pager_range(self):
        """
        显示的页码范围
        :return: (begin,stop)
        """
        half = (self.max_show_page) // 2
        # 如果数据总页数 < 11
        if self.all_page < self.max_show_page:
            begin = 1
            stop = self.all_page + 1
        # 如果数据总页数 > 11
        else:
            # 如果当前页 <= 5,永远显示1,11
            if self.actual_current_page <= half:

                begin = 1
                stop = self.max_show_page + 1
            else:
                if self.actual_current_page + half > self.all_page:
                    # begin = self.actual_current_page - half
                    begin = self.all_page - self.max_show_page + 1
                    stop = self.all_page + 1
                else:
                    begin = self.actual_current_page - half
                    stop = self.actual_current_page + half + 1

        return (begin,stop)



    def pager_str(self):
        # v = '<a href="/custom.html?page=1">1</a>'
        # return v
        page_list = []
        begin, stop = self.pager_range

        # 上一页按钮
        if self.actual_current_page <= 1:
            prev = '<li><a href="#">上一页</a></li>'
        else:
            prev = '<li><a href="{}?page={}">上一页</a></li>'.format(self.base_url,self.actual_current_page-1)
        page_list.append(prev)

        # 页码按钮
        for i in range(begin,stop):
            if i == self.actual_current_page:
                tmp = '<li class="active"><a href="{}?page={}">{}</a></li>'.format(self.base_url,i,i)
            else:
                tmp = '<li><a href="{}?page={}">{}</a></li>'.format(self.base_url,i,i)
            page_list.append(tmp)

        # if self.actual_current_page >= self.all_pager:
        #     after = '<li><a href="#">下一页</a></li>'
        # else:
        #     after = '<li><a href="{}?page={}">下一页</a></li>'.format(self.base_url,self.actual_current_page+1)
        # page_list.append(after)

        # 下一页按钮
        if self.actual_current_page >= self.all_page:
            after = '<li><a href="#">下一页</a></li><span>({start}-{end}/共{total})</span>'.format(
                start=self.start+1 if self.start<self.all_count else self.all_count,
                end=self.end if self.end<self.all_count else self.all_count,
                total=self.all_count)
        else:
            after = '<li><a href="{url}?page={next_page}">下一页</a></li><span>({start}-{end}/共{total})</span>'.format(
                url=self.base_url,
                next_page=self.actual_current_page+1,
                start=self.start+1 if self.start<self.all_count else self.all_count,
                end=self.end if self.end<self.all_count else self.all_count,
                total=self.all_count
            )
        page_list.append(after)

        return " ".join(page_list)
pagers.py
from .utils.pager2 import PageInfo
from django.shortcuts import render
from django.views import View
from . import models

class Index(View):
    def get(self,request):
        page = request.GET.get("page")
        product_obj_list = models.Product.objects.all()
        # all_count = product_obj_list.count()

        page_info = PageInfo(product_obj_list,page,"")

        # product_obj_list_new = product_obj_list[page_info.start:page_info.end]  # 封装到pager里

        context = {
            # "product_obj_list":product_obj_list_new,
            "pager":page_info,
        }

        return render(request,"page.html",context)
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.5-dist/css/bootstrap.min.css">
</head>
<body>



    <ol>
{#        {% for product_obj in product_obj_list %}#}
        {% for product_obj in pager.items %}
{#             Each "contact" is a Contact model object.#}
            <li>{{ product_obj }}</li>
        {% endfor %}
    </ol>
    <nav aria-label="Page navigation">
        <ul class="pagination">
        {{ pager.pager_str|safe }}
        </ul>
    </nav>
    {{ pager.pager_str|safe }}

</body>
</html>
page.html

示例3.3 增加url里的QueryDict

class PageInfo(object):
    def __init__(self,items,current_page,base_url,page_param_dict,per_page=10,max_show_page=11):
        self._items = items
        self.per_page = per_page
        self.all_count = self._items.count()
        self._current_page = current_page
        self.max_show_page = max_show_page
        self.base_url = base_url
        self.page_param_dict = page_param_dict

    @property
    def items(self):
        return self._items[self.start:self.end]

    @property
    def actual_current_page(self):
        """
        涉及到(<=0,<0<=all_page,>all_page)
        :return:
        """
        try:
            current_page = int(self._current_page)
            if current_page > self.all_page:
                current_page = self.all_page
            elif current_page <= 0:
                current_page = 1

        except Exception as e:
            current_page = 1
        return current_page


    @property
    def all_page(self):
        all_page, plus = divmod(self.all_count, self.per_page)
        if plus:
            all_page += 1
        return all_page

    @property
    def start(self):
        return (self.actual_current_page-1) * self.per_page

    @property
    def end(self):
        return self.actual_current_page * self.per_page

    @property
    def pager_range(self):
        """
        显示的页码范围
        :return: (begin,stop)
        """
        half = (self.max_show_page) // 2
        # 如果数据总页数 < 11
        if self.all_page < self.max_show_page:
            begin = 1
            stop = self.all_page + 1
        # 如果数据总页数 > 11
        else:
            # 如果当前页 <= 5,永远显示1,11
            if self.actual_current_page <= half:

                begin = 1
                stop = self.max_show_page + 1
            else:
                if self.actual_current_page + half > self.all_page:
                    # begin = self.actual_current_page - half
                    begin = self.all_page - self.max_show_page + 1
                    stop = self.all_page + 1
                else:
                    begin = self.actual_current_page - half
                    stop = self.actual_current_page + half + 1

        return (begin,stop)


    def pager_str(self):
        # v = '<a href="/custom.html?page=1">1</a>'
        # return v
        page_list = []
        begin,stop = self.pager_range

        # 上一页按钮
        if self.actual_current_page <= 1:
            prev = '<li><a href="#">上一页</a></li>'
        else:
            self.page_param_dict["page"] = self.actual_current_page-1
            prev = '<li><a href="{}?{}">上一页</a></li>'.format(self.base_url,self.page_param_dict.urlencode())

        page_list.append(prev)

        # 页码按钮
        for i in range(begin,stop):
            self.page_param_dict["page"] = i
            if i == self.actual_current_page:
                tmp = '<li class="active"><a href="{}?{}">{}</a></li>'.format(self.base_url,self.page_param_dict.urlencode(),i)
            else:
                tmp = '<li><a href="{}?{}">{}</a></li>'.format(self.base_url,self.page_param_dict.urlencode(),i)
            page_list.append(tmp)

        # 下一页按钮
        if self.actual_current_page >= self.all_page:
            after = '<li><a href="#">下一页</a></li>'
        else:
            self.page_param_dict["page"] = self.actual_current_page+1
            after = '<li><a href="{}?{}">下一页</a></li>'.format(self.base_url,self.page_param_dict)
        page_list.append(after)

        # if self.actual_current_page >= self.all_pager:
        #     after = '<li><a href="#">下一页</a></li><span>({start}-{end}/共{total})</span>'.format(
        #         start=self.start+1 if self.start<self.all_count else self.all_count,
        #         end=self.end if self.end<self.all_count else self.all_count,
        #         total=self.all_count)
        # else:
        #     after = '<li><a href="{url}?page={next_page}">下一页</a></li><span>({start}-{end}/共{total})</span>'.format(
        #         url=self.base_url,
        #         next_page=self.actual_current_page+1,
        #         start=self.start+1 if self.start<self.all_count else self.all_count,
        #         end=self.end if self.end<self.all_count else self.all_count,
        #         total=self.all_count
        #     )
        # page_list.append(after)

        return " ".join(page_list)
pager2.py
from .utils.pager2 import PageInfo
from django.shortcuts import render
from django.views import View
from . import models
from django.http.request import QueryDict

class Index(View):
    def get(self,request):

        product_obj_list = models.Product.objects.all()
        page = request.GET.get("page")

        q = QueryDict(mutable=True)  # mutable,可改变的。而request.GET是immutable的。
        q.update(request.GET)
        page_info = PageInfo(product_obj_list,page,"",q)

       # product_obj_list_new = product_obj_list[page_info.start:page_info.end]  # 把这一段封装到PageInfo里了

        context = {
            # "product_obj_list":product_obj_list_new,
            "pager":page_info,
        }

        return render(request,"page.html",context)
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.5-dist/css/bootstrap.min.css">
</head>
<body>



    <ol>
        {% for product_obj in pager.items %}
{#             Each "contact" is a Contact model object.#}
            <li>{{ product_obj }}</li>
        {% endfor %}
    </ol>
    <nav aria-label="Page navigation">
        <ul class="pagination">
        {{ pager.pager_str|safe }}
        </ul>
    </nav>
    {{ pager.pager_str|safe }}

</body>
</html>
page.html

 增加首页、末页

class PageInfo(object):
    def __init__(self,items,current_page,base_url,page_param_dict,per_page=10,max_show_page=11):
        self._items = items
        self.per_page = per_page
        self.all_count = self._items.count()
        self._current_page = current_page
        self.max_show_page = max_show_page
        self.base_url = base_url
        self.page_param_dict = page_param_dict

    @property
    def items(self):
        return self._items[self.start:self.end]

    @property
    def actual_current_page(self):
        """
        涉及到(<=0,<0<=all_page,>all_page)
        :return:
        """
        try:
            current_page = int(self._current_page)
            if current_page > self.all_page:
                current_page = self.all_page
            elif current_page <= 0:
                current_page = 1

        except Exception as e:
            current_page = 1
        return current_page


    @property
    def all_page(self):
        all_page, plus = divmod(self.all_count, self.per_page)
        if plus:
            all_page += 1
        return all_page

    @property
    def start(self):
        return (self.actual_current_page-1) * self.per_page

    @property
    def end(self):
        return self.actual_current_page * self.per_page

    @property
    def pager_range(self):
        """
        显示的页码范围
        :return: (begin,stop)
        """
        half = (self.max_show_page) // 2
        # 如果数据总页数 < 11
        if self.all_page < self.max_show_page:
            begin = 1
            stop = self.all_page + 1
        # 如果数据总页数 > 11
        else:
            # 如果当前页 <= 5,永远显示1,11
            if self.actual_current_page <= half:

                begin = 1
                stop = self.max_show_page + 1
            else:
                if self.actual_current_page + half > self.all_page:
                    # begin = self.actual_current_page - half
                    begin = self.all_page - self.max_show_page + 1
                    stop = self.all_page + 1
                else:
                    begin = self.actual_current_page - half
                    stop = self.actual_current_page + half + 1

        return (begin,stop)


    def pager_str(self):
        # v = '<a href="/custom.html?page=1">1</a>'
        # return v
        page_list = []
        begin,stop = self.pager_range

        # 上一页按钮
        if self.actual_current_page <= 1:
            prev = '<li><a href="#">上一页</a></li>'
        else:
            self.page_param_dict["page"] = self.actual_current_page-1
            prev = '<li><a href="{}?{}">上一页</a></li>'.format(self.base_url,self.page_param_dict.urlencode())

        page_list.append(prev)


        self.page_param_dict['page'] = 1
        first = '<li><a href="%s?%s">首页</a></li>' % (self.base_url,self.page_param_dict.urlencode())
        page_list.append(first)
        

        # 页码按钮
        for i in range(begin,stop):
            self.page_param_dict["page"] = i
            if i == self.actual_current_page:
                tmp = '<li class="active"><a href="{}?{}">{}</a></li>'.format(self.base_url,self.page_param_dict.urlencode(),i)
            else:
                tmp = '<li><a href="{}?{}">{}</a></li>'.format(self.base_url,self.page_param_dict.urlencode(),i)
            page_list.append(tmp)

        self.page_param_dict['page'] = self.all_page
        last = '<li><a href="%s?%s">末页</a></li>' % (self.base_url, self.page_param_dict.urlencode())
        page_list.append(last)

        # 下一页按钮
        if self.actual_current_page >= self.all_page:
            after = '<li><a href="#">下一页</a></li>'
        else:
            self.page_param_dict["page"] = self.actual_current_page+1
            after = '<li><a href="{}?{}">下一页</a></li>'.format(self.base_url,self.page_param_dict)
        page_list.append(after)

        # if self.actual_current_page >= self.all_pager:
        #     after = '<li><a href="#">下一页</a></li><span>({start}-{end}/共{total})</span>'.format(
        #         start=self.start+1 if self.start<self.all_count else self.all_count,
        #         end=self.end if self.end<self.all_count else self.all_count,
        #         total=self.all_count)
        # else:
        #     after = '<li><a href="{url}?page={next_page}">下一页</a></li><span>({start}-{end}/共{total})</span>'.format(
        #         url=self.base_url,
        #         next_page=self.actual_current_page+1,
        #         start=self.start+1 if self.start<self.all_count else self.all_count,
        #         end=self.end if self.end<self.all_count else self.all_count,
        #         total=self.all_count
        #     )
        # page_list.append(after)

        return " ".join(page_list)
增加首页、末页
class Page(object):
    def __init__(self, current_page, all_count, base_url, query_params, per_page=10, pager_page_count=11):
        """
        分页初始化
        :param current_page: 当前页码
        :param per_page: 每页显示数据条数
        :param all_count: 数据库中总条数
        :param pager_page_count: 页面上最多显示的页码数量
        """
        self.base_url = base_url
        self.query_params = query_params
        try:
            self.current_page = int(current_page)
            if self.current_page <= 0:
                raise Exception()
        except Exception as e:
            self.current_page = 1

        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><a href="#">上一页</a></li>'
        else:
            self.query_params['page'] = self.current_page - 1
            prev = '<li><a href="%s?%s">上一页</a></li>' % (self.base_url,self.query_params.urlencode())
        page_list.append(prev)

        self.query_params['page'] = 1
        first = '<li><a href="%s?%s">首页</a></li>' % (self.base_url,self.query_params.urlencode())
        page_list.append(first)

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


        self.query_params['page'] = self.pager_count
        last = '<li><a href="%s?%s">末页</a></li>' % (self.base_url, self.query_params.urlencode())
        page_list.append(last)


        if self.current_page >= self.pager_count:
            nex = '<li><a href="#">下一页</a></li>'
        else:
            self.query_params['page'] = self.current_page + 1
            nex = '<li><a href="%s?%s">下一页</a></li>' % (self.base_url, self.query_params.urlencode(),)
        page_list.append(nex)
        page_str = "".join(page_list)
        return page_str
增加首页、末页,无items

 

 

 参考or转发

https://www.cnblogs.com/kongzhagen/p/6640975.html

https://www.cnblogs.com/nulige/p/6558207.html

posted @ 2018-09-14 12:09  fat39  阅读(197)  评论(0编辑  收藏  举报