Django分页器


from django.shortcuts import render
from .models import *
from django.core.paginator import Paginator, EmptyPage


def page(request):
    # 拿到数据库queryset对象
    book_queryset = Book.objects.all()
    # 每页10条数据,并将数据库queryset对象传入
    """类实例化,paginator_set对象方法有count数据总数/num_pages总页数/page_range页码总列表(从1开始),都不需要加括号执行"""
    paginator_set = Paginator(book_queryset, 10)
    # 获取前端发送过来的page值,如果没有page参数(第一次进入页面时)或page参数为空,那么默认为1
    page_num = int(request.GET.get("page", 1))
    # 如果page_num值不在总页数之间,那么paginator_set.page()会报EmptyPage错
    try:
    """类实例化,对象中包含每一页10条书籍的对象,对象方法有has_next()是否有下一页/has_previous()是否有上一页/next_page_number()下一页/previous_page_number()上一页/start_index()当前页的第一条数据在数据总数中的排序值(1开始计数)/end_index()"""
        current_page = paginator_set.page(page_num)
    except EmptyPage as e:
        current_page = paginator_set.page(1)
    # 如果总页数大于11,那么按照下面的逻辑进行判断
    if paginator_set.num_pages > 11:
        # 当前页减去5小于1,那么页数维持在(1, 11)
        if page_num-5 < 1:
            page_range = range(1, 11)
        # 当前页加上5大于总页数,那么页数维持在(总页数-9, 尾页+1)
        elif page_num+5 > paginator_set.num_pages:
            page_range = range(paginator_set.num_pages-9, paginator_set.num_pages+1)
        # 当前页-5不小于1而且+5不大于总页数,那么页数维持在(当前页-5, 当前页+6)
        else:
            page_range = range(page_num-5, page_num+6)
    # 如果总页数小于11,那么页数和总页数一样,不做任何逻辑判断
    else:
        page_range = paginator_set.page_range
    return render(request, "page.html", locals())
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <link rel="stylesheet" href="/static/bootstrap-3.4.1-dist/css/bootstrap.min.css">
    <script src="/static/bootstrap-3.4.1-dist/js/bootstrap.min.js">script>
    <script src="/static/jQuery3.6.js">script>
head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-10 col-md-offset-1">
            <table class="table table-bordered table-striped">
                <thead>
                <tr>
                    <th>序号th>
                    <th>书籍名称th>
                    <th>书籍价格th>
                tr>
                thead>
                <tbody>
                {# 循环paginator_set.page()实例化的对象,可以取到每一个的书籍对象 #}
                {% for current in current_page %}
                    {# 如果是每一页第一条数据, 那么序号则展示其start_index,start_index()返回值的计算方法是:(分页条数*(当前页-1))+1 #}
                    {% if current.first %}
                        <tr>
                            <td>{{ current_page.start_index }}td>
                            <td>{{ current.title }}td>
                            <td>{{ current.price }}td>
                        tr>
                    {# 如果不是每一页第一条数据,那么利用start_index()方法计算的值加counter0的值,结果范围为(start_index()+1,start_index()+9) #}
                    {% else %}
                        <tr>
                            <td>{{ forloop.counter0|add:current_page.start_index }}td>
                            <td>{{ current.title }}td>
                            <td>{{ current.price }}td>
                        tr>
                    {% endif %}
                {% endfor %}
                tbody>
            table>

            <div class="text-center">
                <nav aria-label="Page navigation">
                    <ul class="pagination">
                        {# 首页按钮,固定page=1 #}
                        <li>
                            <a href="?page=1" aria-label="Previous">
                                <span aria-hidden="true">首页span>
                            a>
                        li>

                        {# 如果上一页还有数据,那么让其可继续点击进入上一页 #}
                        {% if current_page.has_previous %}
                            <li>
                                <a href="?page={{ current_page.previous_page_number }}" aria-label="Previous">
                                    <span aria-hidden="true">«span>
                                a>
                            li>
                        {# 如果上一页没有数据了,那么不让做任何操作 #}
                        {% else %}
                            <li class="disabled">
                                <span aria-hidden="true">«span>
                            li>
                        {% endif %}

                        {# 由后端经逻辑判断后的page_range页数列表进行循环 #}
                        {% for page in page_range %}
                            {# 如果循环的页码与当前查看的页码相等,那么就让其高亮显示 #}
                            {% if page == page_num %}
                                <li class="active"><a href="?page={{ page }}">{{ page }}a>li>
                            {% else %}
                                <li><a href="?page={{ page }}">{{ page }}a>li>
                            {% endif %}
                        {% endfor %}

                        {# 如果当前页还有下一页,那么让其可以点击进入下一页 #}
                        {% if current_page.has_next %}
                            <li>
                                <a href="?page={{ current_page.next_page_number }}" aria-label="Next">
                                    <span aria-hidden="true">»span>
                                a>
                            li>
                        {# 如果当前页没有下一页了,那么不让做任何操作 #}
                        {% else %}
                            <li class="disabled">
                                <span aria-hidden="true">»span>
                            li>
                        {% endif %}

                        {# 跳转到尾页,让page参数直接等于总页数 #}
                        <li>
                            <a href="?page={{ paginator_set.num_pages }}" aria-label="Previous">
                                <span aria-hidden="true">尾页span>
                            a>
                        li>
                    ul>
                nav>
            div>
        div>
    div>
div>
body>
html>

ORM批量插入数据方法推荐

from .models import *
book_list = []
for i in range(100):
    book_obj = Book(
        title="book_%s" % i,
        price=i * i,
    )
    book_list.append(book_obj)
Book.objects.bulk_create(book_list)

分页器编写思路

"""
后端:
    1 先要有一个数据库queryset对象
    2 实例化一个分页器对象,把数据库queryset对象和分页条数传入
    3 获取到前端发送过来的页码值,页码值可能为空,设置默认值为1
    4 根据前端发送过来的页码值,进行分页器对象.page(number)得到每一页的数据对象
    5 前端发送过来的页码值可能有异常,所以通过try捕获错误,如果有错误将页码值设置为1
    6 对页码的左、中、右展示情况进行逻辑判断

前端:
    1 先遍历每一页的数据对象,展示到表格
    2 序号不应按主键id进行展示,所以会有一个判断,通过每一页的数据对象的子对象.start_index与forloop.counter0相加即可成功展示
    3 页码的首页尾页,上一页下一页(是否还有上一页下一页),页码高亮展示
"""