Django的分页器Paginator

1.使用分页器前需要准备好数据:

准备工作:创建项目和应用。在setting中设置该有的配置以及路由。

在创建的app中的models.py文件中创建该数据库模型:

from django.db import models
class Book(models.Model):
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=1)

    class Meta:
        db_table = 'Book'

生成该模型: 

python manage.py makemigrations

python manage.py migrate

绑定路由:

from django.contrib import admin
from django.urls import path
from app1 import views

urlpatterns = [
    path("admin/", admin.site.urls),
    path("create/", views.create),
    path("books/", views.index),
]

在views.py文件中插入数据:

from django.shortcuts import render,HttpResponse
from .models import Book

def create(request):
    Booklist=[]
    for i in range(101):
        Booklist.append(Book(title="book"+str(i),price=i*2))
    Book.objects.bulk_create(Booklist)
    return HttpResponse("插入成功")

2.分页器Paginator的基础语法

views.py:

from django.core.paginator import Paginator
def index(request):
    book_list = Book.objects.all() #总数据
    #(1)分页对象
    paginator = Paginator(book_list,5)  #每页5条数据

    #分页信息
    print(paginator.count) #总数据的数量 1000
    print(paginator.num_pages)  #分页的数量  1000/5=200页
    print(paginator.page_range)  #分页列表range(1,201)


    #(2)获取某页对象
    visit_page_num = request.GET.get('page',1)#没有在导航栏输入page的话默认为1
    page = paginator.page(visit_page_num)  #paginator.page(哪一页的数据)
    #获取该页的所有数据
    # 方式一:
    print(page.object_list)

    # #方式二:
    for book in page:
        print(book)

    #某页对象其他属性

    print(page.next_page_number()) #下一页
    print(page.previous_page_number())  #上一页
    print(page.has_next())  #是否有下一页   True
    print(page.has_previous())  #是否有上一页  True

    # page_book_list = page.object_list



    return render(request,'index.html',{"page":page})

html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<ul>
    {% for book in page %}
        <li>{{ book.title }}:{{ book.price }}</li>
    {% endfor %}
</ul>
</body>
</html>

3.分页器Paginator的调整

问题一:

page页数超过或低于该模型的最大页数时:

from django.core.paginator import Paginator
def index(request):
    book_list = Book.objects.all() #总数据
    #(1)分页对象
    paginator = Paginator(book_list,5)  #每页5条数据

    #分页信息
    print(paginator.count) #总数据的数量 1000
    print(paginator.num_pages)  #分页的数量  1000/5=200页
    print(paginator.page_range)  #分页列表range(1,201)

    try:   #使用try的作用,把低于或者超过该页数的重定向成第一页数
        #(2)获取某页对象
        visit_page_num = request.GET.get('page',1)#没有在导航栏输入page的话默认为1
        page = paginator.page(visit_page_num)  #paginator.page(哪一页的数据)
        #获取该页的所有数据
        # 方式一:
        print(page.object_list)

        # #方式二:
        for book in page:
            print(book)

        #某页对象其他属性

        print(page.next_page_number()) #下一页
        print(page.previous_page_number())  #上一页
        print(page.has_next())  #是否有下一页   True
        print(page.has_previous())  #是否有上一页  True

        # page_book_list = page.object_list

    except Exception as e:
        page = paginator.page(1) #使用try的作用,把低于或者超过该页数的重定向成第一页数


    return render(request,'index.html',{"page":page})

问题二:

在这里只是前端的页面,怎么点击按钮都没用,该怎么办?

在前端和后端中添加页数的按钮,不可能让用户在导航栏输入page吧?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

</head>
<body>
<ul>
    {% for book in page %}
        <li>{{ book.title }}:{{ book.price }}</li>
    {% endfor %}

</ul>
<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">&laquo;</span>
      </a>
    </li>
    <li><a href="#">1</a></li>
    <li><a href="#">2</a></li>
    <li><a href="#">3</a></li>
    <li><a href="#">4</a></li>
    <li><a href="#">5</a></li>
    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">&raquo;</span>
      </a>
    </li>
  </ul>
</nav>
</body>
</html>

在后端中我们可以使用哪个法子可以把所有的页数展示出来?

那么就是上面提及到的

print(paginator.page_range)  #分页列表range(1,14)

顾名思义,page_range就是一个列表,我们可以for循环它,来展示我们的页数。

所有我们要在前端(更改成for循环)和后端(导入前端模板paginator参数)代码中更改:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

</head>
<body>
<ul>
    {% for book in page %}
        <li>{{ book.title }}:{{ book.price }}</li>
    {% endfor %}

</ul>
<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">&laquo;</span>
      </a>

        {% for i in paginator.page_range %}
            <li><a href="">{{ i }}</a></li>
        {% endfor %}

      <a href="#" aria-label="Next">
        <span aria-hidden="true">&raquo;</span>
      </a>
    </li>
  </ul>
</nav>
</body>
</html>
from django.core.paginator import Paginator
def index(request):
    book_list = Book.objects.all() #总数据
    #(1)分页对象
    paginator = Paginator(book_list,5)  #每页5条数据

    #分页信息
    print(paginator.count) #总数据的数量 1000
    print(paginator.num_pages)  #分页的数量  1000/5=200页
    print(paginator.page_range)  #分页列表range(1,201)

    try:   #使用try的作用,把低于或者超过该页数的重定向成第一页数
        #(2)获取某页对象
        visit_page_num = request.GET.get('page',1)#没有在导航栏输入page的话默认为1
        page = paginator.page(visit_page_num)  #paginator.page(哪一页的数据)
        #获取该页的所有数据
        # 方式一:
        print(page.object_list)

        # #方式二:
        for book in page:
            print(book)

        #某页对象其他属性

        print(page.next_page_number()) #下一页
        print(page.previous_page_number())  #上一页
        print(page.has_next())  #是否有下一页   True
        print(page.has_previous())  #是否有上一页  True

        # page_book_list = page.object_list

    except Exception as e:
        page = paginator.page(1) #使用try的作用,把低于或者超过该页数的重定向成第一页数


    return render(request,'index.html',{"page": page,"paginator":paginator})

结果:

解决按钮不能点击问题:

        {% for i in paginator.page_range %}
            <li><a href="/books/?page={{ i }}">{{ i }}</a></li>
        {% endfor %}

我在前端的a标签里面添加我们的路径,i变量为页数。

然后便可点击。

按钮的颜色:

意思点击某个按钮时,这个按钮会变成深色,让用户知道自己在哪一页。

原理:在导航栏的page的参数值中,前端的模板语法获取当前页数的page值,然后再前端模板语法中把page值加颜色深,之后就在前端中可以看到页数的值加深

前端判断:

里面的visit_page_num从后端获取

        {% for i in paginator.page_range %}
            
            {% if i  == visit_page_num %}
                <li class="active"><a href="/books/?page={{ i }}">{{ i }}</a></li>
            {% else %}
                <li><a href="/books/?page={{ i }}">{{ i }}</a></li>
            {% endif %}

        {% endfor %}

后端导入:vist_page_num

return render(request, 'index2.html', {"page": page, "paginator": paginator,"visit_page_num": visit_page_num})

结果:

问题三:

添加上一页和下一页的功能。

  <ul class="pagination">
    <li>
      <a href="/books/?page={{ page.previous_page_number }}" aria-label="Previous">
        <span aria-hidden="true">上一页</span>
      </a>

        {% for i in paginator.page_range %}
            
            {% if i  == visit_page_num %}
                <li class="active"><a href="/books/?page={{ i }}">{{ i }}</a></li>
            {% else %}
                <li><a href="/books/?page={{ i }}">{{ i }}</a></li>
            {% endif %}

        {% endfor %}

      <a href="/books/?page={{ page.next_page_number }}" aria-label="Next">
        <span aria-hidden="true">下一页</span>
      </a>
    </li>
  </ul>

但是有存在的问题,就是到达第一页的时候,再点击上一页会报错,这是因为该方法有检查上一页是否有值,如果没有值那么就会报错。(下一页也是)。

所以我们要添加判断:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">

</head>
<body>
<div class="container">

    <h4>分页器</h4>
    <ul>

        {% for book in page %}
             <li>{{ book.title }} -----{{ book.price }}</li>
        {% endfor %}

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

            {% if page.has_previous %}
                <li>
                    <a href="/books?page={{ page.previous_page_number }}" aria-label="Previous">
                        <span aria-hidden="true">上一页</span>
                    </a>
                </li>
            {% else %}
                <li class="disabled">
                    <a href="/books?page={{ page.previous_page_number }}" aria-label="Previous">
                        <span aria-hidden="true">上一页</span>
                    </a>
                </li>

            {% endif %}


            {% for i in paginator.page_range %}
                {% if i == visit_page_num %}
                    <li class="active"><a href="/books/?page={{ i }}">{{ i }}</a></li>
                {% else %}
                    <li><a href="/books/?page={{ i }}">{{ i }}</a></li>
                {% endif %}
            {% endfor %}

            {% if page.has_next %}
                <li>
                    <a href="/books?page={{ page.next_page_number }}" aria-label="Next">
                        <span aria-hidden="true">下一页</span>
                    </a>
                </li>
            {% else %}
                <li class="disabled">
                    <a href="/books?page={{ page.next_page_number }}" aria-label="Next">
                        <span aria-hidden="true">下一页</span>
                    </a>
                </li>

            {% endif %}
        </ul>
    </nav>
</div>
</body>
</html>

原理图:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值