Django_分頁

目錄

基本語法css

示例html

 

 

簡介

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.htmldjango

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

相關文章
相關標籤/搜索