Django之分页

1. Django的内置分页

1.1 views.py

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

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

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

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

1.2 index.html

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

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

2. 扩展Django内置分页

2.1 views.py

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

class CustomPaginator(Paginator):
    def __init__(self, current_page, max_pager_num, *args, **kwargs):
        self.current_page = int(current_page)
        self.max_pager_num = max_pager_num
        super(CustomPaginator, self).__init__(*args, **kwargs)

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

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

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

2.2 index.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<ul>
    {% for item in posts %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>
<div class="pagination">
<span class="step-links">
    {% if posts.has_previous %}
        <a href="?p={{ posts.previous_page_number }}">Previous</a>
    {% endif %}

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

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

3. 自定义分页

3.1 自定义分页插件

pager.py

class Paginator(object):
    def __init__(self, totalCount, currentPage, perPageItemNum=10, maxPageNum=11):
        """
        totalCount:数据总个数
        currentPage:当前页
        perPageItemNum: 每页显示的行数
        maxPageNum:最多显示的页码个数
        """
        self.total_count = totalCount
        try:
            v = int(currentPage)
            if v <= 0:
                v = 1
            self.current_page = v
        except Exception as e:
            self.current_page = 1
        self.per_page_item_num = perPageItemNum
        self.max_page_num = maxPageNum

    @property
    def start(self):
        """数据切片的起始位置"""
        return (self.current_page-1) * self.per_page_item_num

    @property
    def end(self):
        """数据切片的结束位置"""
        return self.current_page * self.per_page_item_num

    @property
    def num_pages(self):
        """总的页数"""
        a, b = divmod(self.total_count, self.per_page_item_num)
        if b == 0:
            return a
        return a + 1

    def page_num_range(self):
        """页码范围"""
        part = int(self.max_page_num / 2)
        # 总的页数少于默认要显示的页码数
        if self.num_pages < self.max_page_num:
            return range(1, self.num_pages + 1)
        # 当前页码处于第一页的前一半位置
        if self.current_page - part < 1:
            return range(1, self.max_page_num + 1)
        # 当前页码处于最后一页的后一半位置
        if self.current_page + part > self.num_pages:
            return range(self.num_pages - self.max_page_num + 1, self.num_pages + 1)
        return range(self.current_page - part, self.current_page + part + 1)

    def page_str(self):
        """生成所有的页码"""
        # 创建一个保存所有页码的容器
        page_list = []

        # 生成首页和上一页的页码
        first = "<li><a href='?p=1'>首页</a></li>"
        page_list.append(first)
        if self.current_page == 1:
            the_prev = "<li><a href='#'>上一页</a></li>"
        else:
            the_prev = "<li><a href='?p=%s'>上一页</a></li>" % (self.current_page - 1, )
        page_list.append(the_prev)

        # 生成中间所有页的页码
        for i in self.page_num_range():
            if i == self.current_page:
                temp = "<li class='active'><a href='?p=%s'>%s</a></li>" % (i, i, )
            else:
                temp = "<li><a href='?p=%s'>%s</a></li>" % (i, i, )
            page_list.append(temp)

        # 生成下一页和尾页的页码
        if self.current_page == self.num_pages:
            the_next = "<li><a href='#'>下一页</a></li>"
        else:
            the_next = "<li><a href='?p=%s'>下一页</a></li>" % (self.current_page + 1, )
        page_list.append(the_next)
        last = "<li><a href='?p=%s'>尾页</a></li>" % (self.num_pages, )
        page_list.append(last)

        # 列表容器中的各个页码转换为字符串
        result = ''.join(page_list)
        return result

3.2 在后台函数中调用自定义分页插件

views.py

user_list = []
for i in range(1, 999):
    temp = {'username': 'root' + str(i), 'age': i, }
    user_list.append(temp)
    
def index(request):
    # 获取当前页码号
    current_page = int(request.GET.get('p'))
    # 导入自定义分页插件
    from app01.pager import Paginator
    # 参数依次为: 数据总个数, 当前页码号, 每页显示的行数, 最多显示的页码个数
    # 后两个参数默认为: 10, 11
    obj = Paginator(999, current_page,)
    # obj对象中可调用的属性(方法):
    #     start       当前页的起始条目索引
    #     end         当前页的结束条目索引
    #     page_str()  生成的所有页码结构和样式
    data_list = user_list[obj.start:obj.end]
    return render(request, 'index.html', {'data': data_list, 'page_obj': obj, })

3.3 模板文件index.html

<!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 row in data %}
                <li>{{ row.username }} -- {{ row.age }}</li>
            {% endfor %}
        </ul>

        {# 分页的内容 #}
        <ul class="pagination">
            {{ page_obj.page_str|safe }}
        </ul>
</body>
</html>

 

posted @ 2020-07-27 20:31  Praywu  阅读(173)  评论(0编辑  收藏  举报