django自定义分页及内置分页

分页

当数据库中数据有很多,我们通常会在前端页面做分页展示。

分页的数据可以在前端页面实现,也可以在后端实现分页。

后端实现分页的原理就是每次只请求一页数据。

准备工作

我们使用脚本批量创建一些测试数据(将下面的代码保存到bulk_create.py文件中放到Django项目的根目录,直接执行即可。):

import os
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day71.settings")
    import django
    django.setup()
    from app01 import  models
    # obj = [models.Book(price= i,title='沙河{}'.format(i)) for i in range(1000)]
    #
    # models.Book.objects.bulk_create(obj,100)


    obj = [models.Author(age= i, name='猪八戒{}'.format(i)) for i in range(500)]

    models.Author.objects.bulk_create(obj,100)

自定义分页

def publisher_list(request):
    # 从URL中取当前访问的页码数
    try:
        current_page = int(request.GET.get('page'))
    except Exception as e:
        # 取不到或者页码数不是数字都默认展示第1页
        current_page = 1
    # 总数据量
    total_count = models.Publisher.objects.count()
    # 定义每页显示多少条数据
    per_page = 10
    # 计算出总页码数
    total_page, more = divmod(total_count, per_page)
    if more:
        total_page += 1
    # 定义页面上最多显示多少页码(为了左右对称,一般设为奇数)
    max_show = 11
    half_show = max_show // 2
    # 计算一下页面显示的页码范围
    if total_page <= max_show:  # 总页码数小于最大显示页码数
        page_start = 1
        page_end = total_page
    elif current_page + half_show >= total_page:  # 右边越界
        page_end = total_page
        page_start = total_page - max_show
    elif current_page - half_show <= 1:  # 左边越界
        page_start = 1
        page_end = max_show
    else:  # 正常页码区间
        page_start = current_page - half_show
        page_end = current_page + half_show
    # 数据索引起始位置
    data_start = (current_page-1) * per_page
    data_end = current_page * per_page

    publisher_list = models.Publisher.objects.all()[data_start:data_end]

    # 生成页面上显示的页码
    page_html_list = []
    page_html_list.append('<nav aria-label="Page navigation"><ul class="pagination">')
    # 加首页
    first_li = '<li><a href="/publisher_list/?page=1">首页</a></li>'
    page_html_list.append(first_li)
    # 加上一页
    if current_page == 1:
        prev_li = '<li><a href="#"><span aria-hidden="true">&laquo;</span></a></li>'
    else:
        prev_li = '<li><a href="/publisher_list/?page={}"><span aria-hidden="true">&laquo;</span></a></li>'.format(current_page - 1)
    page_html_list.append(prev_li)
    for i in range(page_start, page_end + 1):
        if i == current_page:
            li_tag = '<li class="active"><a href="/publisher_list/?page={0}">{0}</a></li>'.format(i)
        else:
            li_tag = '<li><a href="/publisher_list/?page={0}">{0}</a></li>'.format(i)
        page_html_list.append(li_tag)
    # 加下一页
    if current_page == total_page:
        next_li = '<li><a href="#"><span aria-hidden="true">&raquo;</span></a></li>'
    else:
        next_li = '<li><a href="/publisher_list/?page={}"><span aria-hidden="true">&raquo;</span></a></li>'.format(current_page + 1)
    page_html_list.append(next_li)
    # 加尾页
    page_end_li = '<li><a href="/publisher_list/?page={}">尾页</a></li>'.format(total_page)
    page_html_list.append(page_end_li)
    page_html_list.append('</ul></nav>')
    page_html = "".join(page_html_list)
    return render(request, "publisher_list.html", {"publisher_list": publisher_list, "page_html": page_html})
稳扎稳打版
class Page():
    """自定义分页(Bootstrap版)"""
    def __init__(self, page_num, total_count, url_prefix, per_page=10, max_page=11):
        """

        :param page_num:     用户提交的当前页码数
        :param total_count:  数据总数
        :param url_prefix:   当前页面a标签的href的前缀 请求的URL
        :param per_page:     每个页面显示的数据数量
        :param max_page:     页面上最多显示几个页码
        """
        self.url_prefix = url_prefix
        self.max_page = max_page    #
        self.per_page = per_page  # 每一页显示多少条数据

        # 总共需要多少页码来展示
        total_page, m = divmod(total_count, per_page)
        if m:
            total_page += 1
        self.total_page = total_page

        try:
            page_num = int(page_num)
            #     如果输入的最大页数超过了最大页码,默认返回最后一页
            if page_num > total_page:
                page_num = total_page
        except Exception as e:
            # 当输入的页码不是正经数字的时候,默认返回第一页
            page_num = 1

        self.page_num = page_num

        # 定义两个变量保存数据从哪儿取到哪儿
        if total_count:
            self.data_start = (page_num - 1) * self.per_page
        else:
            # 如果数据库没有数据返回第一页
            self.data_start=0
        self.data_end = page_num * self.per_page

        # 页面上总共展示多少页码
        if total_page < self.max_page:
            self.max_page = total_page

        # 页面上展示的页码从哪儿开始
        page_start = page_num - (self.max_page // 2)
        # 页面上展示的页码到哪儿结束
        page_end = page_num + (self.max_page // 2)

        if page_start <= 1:
            page_start = 1
            page_end = self.max_page

        if page_end >= total_page:
            page_end = total_page
            page_start = total_page - self.max_page + 1

        self.page_start = page_start
        self.page_end = page_end

    @property
    def start(self):
        return self.data_start

    @property
    def end(self):
        return self.data_end

    # 自己拼接分页的HTML代码
    def page_html(self):
        html_str_list = []

        # 添加首页

        tmp = '<li><a href="{}?page=1">首页</a></li>'.format(self.url_prefix)
        html_str_list.append(tmp)
        # 添加上一页 如果上一页为第一页则不可用
        if self.page_num <= 1:
            tmp = '<li class="disabled"><a href="#"><span aria-hidden="true">&laquo;</span></a></li>'
        else:
            tmp = '<li><a href="{0}?page={1}" aria-label="Previous">' \
                  '<span aria-hidden="true">&laquo;</span></a></li>'.format(self.url_prefix, self.page_num - 1)

        html_str_list.append(tmp)

        for i in range(self.page_start, self.page_end + 1):
            if i == self.page_num:

                tmp = '<li class="active"><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix, i)

            else:

                tmp = '<li><a href="{0}?page={1}">{1}</a></li>'.format(self.url_prefix, i)

            html_str_list.append(tmp)

        # 添加下一页 如果下一页为最后一页则不可用
        if self.page_num >= self.total_page:
            tmp = '<li class="disabled"><a href="#"><span aria-hidden="true">&raquo;</span></a></li>'
        else:
            tmp = '<li><a href="{0}?page={1}"><span aria-hidden="true">&raquo;</span></a></li>'.format(self.url_prefix,
                                                                                                       self.page_num + 1)
        html_str_list.append(tmp)

        # 添加尾页
        tmp = '<li><a href="{0}?page={1}">尾页</a></li>'.format(self.url_prefix, self.total_page)
        html_str_list.append(tmp)

        page_html = ''.join(html_str_list)
        return page_html
封装保存版
def author(request):
    # 从URL中取当前访问的页码数
    page_num = request.GET.get('page')
    # 比len(models.Publisher.objects.all())更高效
    # 取到当前数据库数据的个数
    total_count = models.Author.objects.all().count()
    # 实例化一个分页对象
    page = Page(page_num, total_count,url_prefix='/author/',per_page=10, max_page=7)
    # 取到当前每页要展示的数据
    all_author = models.Author.objects.all()[page.start:page.end]
    # 取到自定义分页的代码
    page_html = page.page_html()

    return render(request, 'author.html', {'all_author': all_author, 'page_html': page_html})
封装保存版使用示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="content-Type" charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
</head>
<body>

<div class="container">

    <table class="table  table-bordered">
        <thead>
        <tr>
            <th>序号</th>
            <th>id</th>
            <th>书名</th>
            <th>价格</th>
        </tr>
        </thead>
        <tbody>
        {% for author in all_author %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ author.id }}</td>
                <td>{{ author.name }}</td>

            </tr>

        {% endfor %}


        </tbody>
    </table>


    <nav aria-label="Page navigation">
        <ul class="pagination">

            {{ page_html|safe }}


        </ul>
    </nav>
</div>


</body>
</html>
html部分示例

Django内置分页

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})
内置分页view部分
<!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>
内置分页HTML部分

猜你喜欢

转载自www.cnblogs.com/xu12135/p/9861116.html