自定义分页基础版


basic_paging.rar

# views.py

import copy
from django.shortcuts import render, redirect, HttpResponse, reverse
from .models import *


def employee_list(request):
# 从URL取参数
    page_num = request.GET.get("page")

# 总数据是多少
    total_count = Employee.objects.all().count()

# 每一页显示多少条数据
    per_page = 10

# 总共需要多少页码来展示
    total_page, m = divmod(total_count, per_page)
    if m:
        total_page += 1
    try:
        page_num = int(page_num)
# 如果输入的页码数超过了最大的页码数,默认返回最后一页
        if page_num > total_page:
            page_num = total_page
    except Exception as e:
# 当输入的页码不是正经数字的时候 默认返回第一页的数据
        page_num = 1

    if page_num < 1:
        page_num = 1

# 定义两个变量保存数据从哪儿取到哪儿
    data_start = (page_num - 1) * per_page
    data_end = page_num * per_page

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

    half_max_page = max_page // 2
# 页面上展示的页码从哪儿开始
    page_start = page_num - half_max_page
# 页面上展示的页码到哪儿结束
    page_end = page_num + half_max_page
# 如果当前页减一半 比1还小
    if page_start <= 1:
        page_start = 1
        page_end = max_page
# 如果 当前页 加 一半 比总页码数还大
    if page_end >= total_page:
        page_end = total_page
        page_start = total_page - max_page + 1

    employees = Employee.objects.all()[data_start:data_end]

# 自己拼接分页的HTML代码
    html_str_list = []

    request_get_data = copy.deepcopy(request.GET)  # 因为无法直接对 request.GET 的返回值 <QueryDict: {}> 进行修改所以需要拷贝一份出来

    request_get_data['page'] = 1
# 加上第一页
    html_str_list.append('<li><a href="/employee_list/?{}">首页</a></li>'.format(request_get_data.urlencode()))

# 判断一下 如果是第一页,就没有上一页
    if page_num <= 1:
        html_str_list.append('<li class="disabled"><a href="#"><span aria-hidden="true">&laquo;</span></a></li>')
    else:
        request_get_data['page'] = page_num - 1
# 加一个上一页的标签
        html_str_list.append('<li><a href="/employee_list/?{}"><span aria-hidden="true">&laquo;</span></a></li>'.format(request_get_data.urlencode()))

    for i in range(page_start, page_end + 1):
        request_get_data['page'] = i
# 如果是当前页就加一个active样式类
        if i == page_num:
            tmp = '<li class="active"><a href="/employee_list/?{}">{}</a></li>'.format(request_get_data.urlencode(), i)
        else:
            tmp = '<li><a href="/employee_list/?{}">{}</a></li>'.format(request_get_data.urlencode(), i)

        html_str_list.append(tmp)

# 加一个下一页的按钮
    # 判断,如果是最后一页,就没有下一页
    if page_num >= total_page:
        html_str_list.append('<li class="disabled"><a href="#"><span aria-hidden="true">&raquo;</span></a></li>')
    else:
        request_get_data['page'] = page_num + 1
        html_str_list.append('<li><a href="/employee_list/?{}"><span aria-hidden="true">&raquo;</span></a></li>'.format(request_get_data.urlencode()))
# 加最后一页
    request_get_data['page'] = total_page
    html_str_list.append('<li><a href="/employee_list/?{}">尾页</a></li>'.format(request_get_data.urlencode()))

    page_html = "".join(html_str_list)

    return render(request, 'employee_list.html', {"employees": employees, "page_html": page_html})

# employee_list.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Title</title>
    <meta name="description" content="">
    <meta name="keywords" content="">
    {% 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>作者名称</th>
            <th>年龄</th>
            <th>薪资</th>
            <th>省份</th>
        </tr>
        </thead>
        <tbody>
        {% for employee in employees %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ employee.name }}</td>
                <td>{{ employee.age }}</td>
                <td>{{ employee.salary }}</td>
                <td>{{ employee.province }}</td>
            </tr>
        {% endfor %}
        </tbody>
    </table>
<!-- 分液器 -->
    <ul class="pagination">
        {{ page_html|safe }}
    </ul>
</div>
</body>
</html>

封装过后的分页


  • 封装过后的好处,不同的视图函数都可以使用封装好的分页

  • 单独的封装过后的分页模块的py文件

utils.rar

  • 封装过后的分页例子

paging_project.rar

# utils/mypage.py

import copy


class Page():

    def __init__(self, page_num, total_count, request_get_data, url_prefix, per_page=10, max_page=11):
 """
        :param page_num: 当前页码数
        :param total_count: 数据总数
        :param request_get_data: GET请求中的参数
        :param url_prefix: a标签href的前缀
        :param per_page: 每页显示多少条数据
        :param max_page: 页面上最多显示几个页码
        """
        self.request_get_data = copy.deepcopy(request_get_data)  # 因为无法直接对 request.GET 的返回值 <QueryDict: {}> 进行修改所以需要拷贝一份出来
        self.url_prefix = url_prefix
        self.max_page = max_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

        if page_num < 1:
            page_num = 1

        self.page_num = page_num

 # 定义两个变量保存数据从哪儿取到哪儿
        self.data_start = (page_num - 1) * per_page
        self.data_end = page_num * per_page

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

        half_max_page = self.max_page // 2
# 页面上展示的页码从哪儿开始
        page_start = page_num - half_max_page
# 页面上展示的页码到哪儿结束
        page_end = page_num + half_max_page
# 如果当前页减一半比1还小的情况
        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

    def page_html(self):
 # 自己拼接分页的HTML代码
        html_str_list = []
 # 加上第一页
        self.request_get_data['page'] = 1
        html_str_list.append('<li><a href="{}?{}">首页</a></li>'.format(self.url_prefix, self.request_get_data.urlencode()))  # .urlencode() 将字段转化成encode编码格式的字符串(即:a=1&b=2&c=3)

# 判断一下 如果是第一页,就没有上一页
        if self.page_num <= 1:
            html_str_list.append('<li class="disabled"><a href="#"><span aria-hidden="true">&laquo;</span></a></li>')
        else:
# 加一个上一页的标签
            self.request_get_data['page'] = self.page_num - 1
            html_str_list.append('<li><a href="{}?{}"><span aria-hidden="true">&laquo;</span></a></li>'.format(self.url_prefix, self.request_get_data.urlencode()))

        for i in range(self.page_start, self.page_end + 1):
# 如果是当前页就加一个active样式类
            self.request_get_data['page'] = i
            if i == self.page_num:
                tmp = '<li class="active"><a href="{}?{}">{}</a></li>'.format(self.url_prefix, self.request_get_data.urlencode(), i)
            else:
                tmp = '<li><a href="{}?{}">{}</a></li>'.format(self.url_prefix, self.request_get_data.urlencode(), i)

            html_str_list.append(tmp)

# 加一个下一页的按钮
        # 判断,如果是最后一页,就没有下一页
        if self.page_num >= self.total_page:
            html_str_list.append('<li class="disabled"><a href="#"><span aria-hidden="true">&raquo;</span></a></li>')
        else:
            self.request_get_data['page'] = self.page_num + 1
            html_str_list.append('<li><a href="{}?{}"><span aria-hidden="true">&raquo;</span></a></li>'.format(self.url_prefix, self.request_get_data.urlencode()))
# 加最后一页
        self.request_get_data['page'] = self.total_page
        html_str_list.append('<li><a href="{}?{}">尾页</a></li>'.format(self.url_prefix, self.request_get_data.urlencode()))

        page_html = "".join(html_str_list)
        return page_html

# views.py

from django.shortcuts import render, redirect, HttpResponse, reverse
from .models import *
from utils.mypage import Page  # 导入封装好的分页模块


def employee_list(request):
# 分页的使用
    total_count = Employee.objects.all().count()  # 获取查询到的数据的总数,.count() 方法比len(Employee.objects.all())更高效
    page_num = request.GET.get("page")  # 获取当前页数
    page_obj = Page(page_num, total_count, request_get_data=request.GET, per_page=10, url_prefix="/employee_list/", max_page=9)
    ret_data = Employee.objects.all()[page_obj.start:page_obj.end]  # 获取指定页数的数据,先查询全部数据然后再进行切片
    page_html = page_obj.page_html()  # 获取分页的html

    return render(request, 'employee_list.html', {'employees': ret_data, 'page_html': page_html})

# employee_list.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Title</title>
    <meta name="description" content="">
    <meta name="keywords" content="">
    {% 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>作者名称</th>
            <th>年龄</th>
            <th>薪资</th>
            <th>省份</th>
        </tr>
        </thead>
        <tbody>
        {% for employee in employees %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ employee.name }}</td>
                <td>{{ employee.age }}</td>
                <td>{{ employee.salary }}</td>
                <td>{{ employee.province }}</td>
            </tr>
        {% endfor %}
        </tbody>
    </table>
<!-- 分液器 -->
    <ul class="pagination">
        {{ page_html|safe }}
    </ul>
</div>
</body>
</html>