3期 58-1 分页

当需要展示的数据量多的时候,就要把一个大长页面分成很多小的页面,并给每个小页面底部添加页面按钮方便切换。

要成功分页,需要告诉服务器4个信息:

  • 数据的总个数是多少
  • 每页展示多少个数据
  • 当前页的页码
  • 每个页面底部需要多少个页码按钮

一、Django内置的分页

Django的内置分页功能非常简单,大致只能做出如下效果:

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

# L为简单的示例数据,真实情况下应从数据库获取
L = []                     
for i in range(1, 550):
    L.append(i)

def index1(request):
    """
    Django内置的分页功能
    """
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    current_page = request.GET.get('p')
    paginator = Paginator(L, 10)         # 实例化出paginator对象。第一参数为数据,第二参数为每页的数据条数
    # paginator.per_page:    每页显示条目数量
    # paginator.count:       数据总个数
    # paginator.num_pages:   总页数
    # paginator.page_range:  总页数的索引范围,如: (1,10),(1,200)
    # paginator.page:        page对象
    try:
        current_page_obj = paginator.page(current_page)
        # current_page_obj.has_next              是否有下一页
        # current_page_obj.next_page_number      下一页页码
        # current_page_obj.has_previous          是否有上一页
        # current_page_obj.previous_page_number  上一页页码
        # current_page_obj.object_list           分页之后的数据列表
        # current_page_obj.number                当前页
        # current_page_obj.paginator             paginator对象
    except PageNotAnInteger:
        current_page_obj = paginator.page(1)                    # 第一页
    except EmptyPage:
        current_page_obj = paginator.page(paginator.num_pages)  # 最后一页

    return render(request, 'index1.html', {'current_page_obj': current_page_obj})
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<ul>
    {% for item in  current_page_obj  %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>


{% if current_page_obj.has_previous %}
    <a href="index1.html?p={{ current_page_obj.previous_page_number }}">上一页</a>
    {% else %}
    <a href="index1.html?p={{ current_page_obj.number }}">上一页</a>
{% endif %}

{% if current_page_obj.has_next %}
    <a href="index1.html?p={{ current_page_obj.next_page_number }}">下一页</a>
    {% else %}
    <a href="index1.html?p={{ current_page_obj.number }}">下一页</a>
{% endif %}


<span>{{ current_page_obj.number }}/{{ current_page_obj.paginator.num_pages }}</span>

</body>
</html>
html

二、对Django内置分页扩展,实现更强的功能

自己写个类,自定义个可以返回页码范围的方法,可实现如下效果:

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

# L为简单的示例数据,真实情况下应从数据库获取
L = []
for i in range(1, 550):
    L.append(i)

class iPaginator(Paginator):
    def __init__(self, current_page_number, count_per_page, *args, **kwargs):
        self.current_page_number = int(current_page_number)
        self.count_per_page = int(count_per_page)
        super(iPaginator, self).__init__(*args, **kwargs)

    def pages_rg(self):
        if self.num_pages <= self.count_per_page:
            pages_rg = [i for i in range(1, self.num_pages + 1)]
        else:
            part = int(self.count_per_page/2)
            if self.current_page_number <= part:
                pages_rg = [i for i in range(1, self.count_per_page + 1)]
            elif self.current_page_number > self.num_pages-part:
                pages_rg = [i for i in range(self.num_pages-self.count_per_page+1, self.num_pages+1)]
            else:
                pages_rg = [i for i in range(self.current_page_number-part, self.current_page_number+part+1)]
        return pages_rg

def index3(request):
    current_page_number = int(request.GET.get('p'))
    count_per_page = 11
    mp = iPaginator(current_page_number, 11, L, 10)

    try:
        current_page_obj = mp.page(current_page_number)
        pages_rg = mp.pages_rg()
    except PageNotAnInteger:
        current_page_obj = mp.page(1)
    except EmptyPage:
        current_page_obj = mp.page(mp.num_pages)
    return render(request, 'index3.html', {'current_page_obj': current_page_obj, "pages_rg": pages_rg})
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<ul>
    {% for item in  current_page_obj  %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

{#上一页#}
{% if current_page_obj.has_previous %}
    <a href="index3.html?p={{ current_page_obj.previous_page_number }}">上一页</a>
    {% else %}
    <a href="index3.html?p={{ current_page_obj.number }}">上一页</a>
{% endif %}

{#页码#}
{% for i in pages_rg %}
    {% if i == current_page_obj.number %}
        <a href="index3.html?p={{ i }}" style="background-color: navy; color: white">{{ i }}</a>
        {% else %}
        <a href="index3.html?p={{ i }}">{{ i }}</a>
    {% endif %}
{% endfor %}

{#下一页#}
{% if current_page_obj.has_next %}
    <a href="index3.html?p={{ current_page_obj.next_page_number }}">下一页</a>
    {% else %}
    <a href="index3.html?p={{ current_page_obj.number }}">下一页</a>
{% endif %}

{#计数#}
<span>{{ current_page_obj.number }}/{{ current_page_obj.paginator.num_pages }}</span>

</body>
</html>
html

三、完全自定义的分页

完全自己写,不依赖任何内置的分页功能,且结合进bootstrap实现更好的效果:

class MyPaginator(object):
    def __init__(self, items_count, current_page_num, per_page_items_count=10,  page_labels_count=11):
        """
        :param items_count: 数据总个数
        :param current_page_num: 当前页的页码
        :param per_page_items_count: 每页显示的数据个数
        :param page_labels_count: 每页的页码标签数量
        """
        self.items_count = items_count
        try:
            v = int(current_page_num)
            if v <= 0:
                v = 1
            self.current_page_num = v
        except Exception as e:
            self.current_page_num = 1
        self.per_page_items_count = per_page_items_count
        self.page_labels_count = page_labels_count

    @property
    def pages_count(self):
        """
        :return: 总页数
        """
        a, b = divmod(self.items_count, self.per_page_items_count)
        if b == 0:
            return a
        return a+1

    def items_show_start_num(self):
        """
        :return: 当前页数据的起始索引号
        """
        return (self.current_page_num-1) * self.per_page_items_count

    def items_show_end_num(self):
        """
        :return:  当前页数据的结束索引号
        """
        return self.current_page_num * self.per_page_items_count

    def previous_page_num(self):
        """
        :return: 当前页的前一页
        """
        if self.current_page_num <= 1:
            return 1
        else:
            return self.current_page_num - 1

    def next_page_num(self):
        """
        :return: 当前页的后一页
        """
        if self.current_page_num >= self.pages_count:
            return self.pages_count
        else:
            return self.current_page_num + 1

    def page_num_range(self):
        """
        :return: 根据当前页的页码数,确定要返回的页码范围
        """
        if self.pages_count <= self.page_labels_count:
            page_num_range = [i for i in range(1, self.pages_count + 1)]
        else:
            part = int(self.page_labels_count/2)
            if self.current_page_num <= part:
                page_num_range = [i for i in range(1, self.page_labels_count + 1)]
            elif self.current_page_num > self.pages_count - part:
                page_num_range = [i for i in range(self.pages_count-self.page_labels_count+1, self.pages_count+1)]
            else:
                page_num_range = [i for i in range(self.current_page_num-part, self.current_page_num+part+1)]
        return page_num_range

    def origin_pager(self, my_url):
        page_num_tag_list = []
        pre_page_num_tag = '<a href="{my_url}?p={page_num}">下一页</a>'.format(my_url=my_url, page_num=self.previous_page_num())
        page_num_tag_list.append(pre_page_num_tag)
        for i in self.page_num_range():
            if i == self.current_page_num:
                page_num_tag = '<a style="color:red" href="{my_url}?p={page_num}">{page_num}</a>'.format(my_url=my_url, page_num=i)
            else:
                page_num_tag = '<a href="{my_url}?p={page_num}">{page_num}</a>'.format(my_url=my_url, page_num=i)
            page_num_tag_list.append(page_num_tag)
        next_page_num_tag = '<a href="{my_url}?p={page_num}">下一页</a>'.format(my_url=my_url, page_num=self.next_page_num())
        page_num_tag_list.append(next_page_num_tag)
        return ''.join(page_num_tag_list)

    def pager(self, my_url):
        """
        结合bootstrap的css,生成漂亮的分页模块
        :param my_url: 要放置分页模块页码的url
        :return: 已经写好的html字符串,可以通过模板语言直接成html代码(注意加safe标识安全,否则不能渲染)
        """
        page_num_tag_list = []
        pre_page_num_tag = '<li><a aria-label="Previous" href="{my_url}?p={page_num}"><span aria-hidden="true">&laquo;</span></a></li>'.format(my_url=my_url, page_num=self.previous_page_num())
        page_num_tag_list.append(pre_page_num_tag)
        for i in self.page_num_range():
            if i == self.current_page_num:
                page_num_tag = '<li class="active"><a href="{my_url}?p={page_num}">{page_num}</a></li>'.format(my_url=my_url, page_num=i)
            else:
                page_num_tag = '<li><a href="{my_url}?p={page_num}">{page_num}</a></li>'.format(my_url=my_url, page_num=i)
            page_num_tag_list.append(page_num_tag)
        next_page_num_tag = '<li><a aria-label="Next" href="{my_url}?p={page_num}"><span aria-hidden="true">&raquo;</span></a></li>'.format(my_url=my_url, page_num=self.next_page_num())
        page_num_tag_list.append(next_page_num_tag)
        return ''.join(page_num_tag_list)
pager.py
from django.shortcuts import render

def index5(request):
    """
    结合进bootstrap的自定义分页
    :param request:
    :return:
    """
    current_page_num = request.GET.get("p")
    from app01.pager import MyPaginator
    myPaginitor_obj = MyPaginator(550, current_page_num, page_labels_count=7)
    items_list = L[myPaginitor_obj.items_show_start_num():myPaginitor_obj.items_show_end_num()]

    p = myPaginitor_obj.pager("index5.html")

    return render(request, 'index5.html', { "myPaginitor_obj": myPaginitor_obj, "items_list": items_list, "p": p})
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
</head>
<body>
<ul>
    {% for i in  items_list %}
        <li>{{ i }}</li>
    {% endfor %}
</ul>

<nav aria-label="Page navigation">
    <ul class="pagination">
        {{ p|safe }}
    </ul>
</nav>


</body>
</html>
html

 

posted @ 2018-01-25 12:35  seaidler  阅读(99)  评论(0)    收藏  举报