django的组件-分页器

引入分页器

在博客园中,如果每个人都发表一篇文章的话,如果咱们不进行分页的话,那么博客园的首页将会变得异常庞大,而且你永远不知道你要拉到什么什么时候才能拉到最底部,此时咱们的分页器就派上了用场,规定每个html页面只显示多少篇文章,给我们带来了大大的便利。

以下是博客园的分页器:

此时咱们需要做的就是这样一个类似的分页器。

分页器demo

创建数据库模型

我们首先做的就是数据库的模型,在这里给Book表定义了两个字段,title和price:

  1. from django.db import models
  2. # Create your models here.
  3. class Book(models.Model):
  4. title = models.CharField(max_length=32)
  5. price = models.DecimalField(max_digits=8, decimal_places=2)

然后我们需要运行数据库迁移命令:

  1. python3 manage.py makemigrations
  2. python3 manage.py migrate

因为没有对数据库进行特殊设置,则默认使用的是sqlite数据库,此时咱们点击pycharm查看新创建的数据库:

此时表创建出来了,那么数据从哪来呢?我们肯定是不可能手写的,所以,我们使用批量增加的方式将100条数据添加到数据库中。

url控制器

需要给程序提供一个入口,当用户输入127.0.0.1:8000/index便进行驶入匹配,如果成功则进入到视图函数中:

  1. from django.contrib import admin
  2. from django.urls import path
  3. from app01 import views
  4. urlpatterns = [
  5. path('admin/', admin.site.urls),
  6. path('index/', views.index),
  7. ]

views视图函数

  1. from django.shortcuts import render
  2. from .models import Book
  3. # Create your views here.
  4. def index(request):
  5. # 通过批量插入bulk_create的方式插入数据,这种方式是一条sql插入100条数据
  6. book_list = []
  7. for i in range(100):
  8. book = Book(title='boos_%s' % i, price=i*i)
  9. book_list.append(book)
  10. Book.objects.bulk_create(book_list)
  11. book_list = Book.objects.all()
  12. return render(request, 'index.html', locals())

此时咱们就成功创建了视图函数,那么如果我们想将所有的数据展示出来的话,咱们需要一个index.html。

templates模板

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  7. </head>
  8. <body>
  9. <ul>
  10. {% for book in book_list %}
  11. <li>{{ book.title }}&nbsp;&nbsp;&nbsp;{{ book.price }}</li>
  12. {% endfor %}
  13. </ul>
  14. </body>
  15. </html>

此时咱们将项目启动起来,然后去浏览器查看:

此时的100条数据全部生成了,要记住的是:当数据批量插入后,需要将批量插入数据库的语句给注释掉。

为什么要用分页器

我们可以查看到100条数据就已经这么多了,但是数据不是一成不变的吗,所以我们需要使用分页器。

导入分页器

在视图函数中导入分页器需要用到这么一句话:

  1. from django.core.paginator import Paginator

此时我们导入的是Paginator类,我们需要实例化成对象,那么这个对象就有自己的属性和方法:

实例化Pagintor对象

需要在视图函数中添加这么一句话来实例化对象:

  1. # 进行实例化
  2. paginator = Paginator(book_list, 10)

这句话的意思就是对book_list进行分页,每页显示10条数据。

那么我们说过,实例化的对象有自己的属性和方法,这里有三个属性,分别是:count、num_pages、page_range

  1. # 实例化的方法和属性
  2. print('总数:', paginator.count)
  3. print('总页数:', paginator.num_pages)
  4. print('页码的列表:', paginator.page_range)

此时让我们重新发送一个请求,然后再pycharm中查看打印结果:

此时就已经获取到了总数、总页数了,此时我们就可以进行下一步操作了。

获取每一页的数据

这个我们可想而知,肯定是1页10条数据,那么我们此时就需要得到这个页码:

  1. # 获取当前页码
  2. current_page_num = int(request.GET.get('page', 1))

request.GET.get('page')获取当前的页码,1代表的是默认显示第一页。

那么我们只是拿到了这个页码,这个数据从哪里拿呢?肯定是从分页器对象里面拿了:

  1. # 根据页码拿到数据
  2. current_page = paginator.page(current_page_num)

此时,这个current_page就是某一页的数据,然后我们需要在模板中更新语法成:

  1. <ul>
  2. {% for book in current_page %}
  3. <li>{{ book.title }}&nbsp;&nbsp;&nbsp;{{ book.price }}</li>
  4. {% endfor %}
  5. </ul>

此时大功告成,我们刷新浏览器就能看到结果了。

如果我们想访问第二页的数据,那么我们需要在浏览器输入http://127.0.0.1:8001/index/?page=2就能访问第二页的数据:

此时咱们就大功告成了,展示下源代码:

  1. # views.py
  2. from django.shortcuts import render
  3. from .models import Book
  4. from django.core.paginator import Paginator
  5. # Create your views here.
  6. def index(request):
  7. '''
  8. # 通过批量插入bulk_create的方式插入数据,这种方式是一条sql插入100条数据
  9. book_list = []
  10. for i in range(100):
  11. book = Book(title='boos_%s' % i, price=i*i)
  12. book_list.append(book)
  13. Book.objects.bulk_create(book_list)
  14. '''
  15. book_list = Book.objects.all()
  16. # 进行实例化
  17. paginator = Paginator(book_list, 10)
  18. # 实例化的方法和属性
  19. print('总数:', paginator.count)
  20. print('总页数:', paginator.num_pages)
  21. print('页码的列表:', paginator.page_range)
  22. # print(request.GET.get('page'))
  23. current_page_num = int(request.GET.get('page', 1))
  24. current_page = paginator.page(current_page_num)
  25. return render(request, 'index.html', locals())
  1. # urls.py
  2. from django.contrib import admin
  3. from django.urls import path
  4. from app01 import views
  5. urlpatterns = [
  6. path('admin/', admin.site.urls),
  7. path('index/', views.index),
  8. ]
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  7. </head>
  8. <body>
  9. <ul>
  10. {% for book in current_page %}
  11. <li>{{ book.title }}&nbsp;&nbsp;&nbsp;{{ book.price }}</li>
  12. {% endfor %}
  13. </ul>
  14. </body>
  15. </html>

没跟上的同学检查下代码。

分页器优化1

你们真的以为大功告成了吗?当然是没有的,举个简单的来说,如果page=-1的话,或者超过了最大页数的话,会怎么样?

报错了,既然报错了咱们就需要捕获异常,因为我们输入的是-1或者10以上都会报错,那么不如让都跳转到第一页去:

  1. # 异常捕获
  2. try:
  3. current_page_num = int(request.GET.get('page', 1))
  4. current_page = paginator.page(current_page_num)
  5. except Exception as e:
  6. current_page = paginator.page(1)

那么当我们再次输入-1的时候,就没有问题了:

那么这个问题就解决了。

分页器优化2

咱们需要在浏览器自己输入这个page是不是特别麻烦,所以,我们需要利用bootstrap来实现点击跳转,具体的就是引入bootstrap的分页器。

我们需要在index.html中添加bootstrap分页器组件:

  1. # 添加bootstrap分页器组件
  2. <nav aria-label="Page navigation">
  3. <ul class="pagination">
  4. <li>
  5. <a href="#" aria-label="Previous">
  6. <span aria-hidden="true">上一页</span>
  7. </a>
  8. </li>
  9. <li><a href="#">1</a></li>
  10. <li><a href="#">2</a></li>
  11. <li><a href="#">3</a></li>
  12. <li><a href="#">4</a></li>
  13. <li><a href="#">5</a></li>
  14. <li>
  15. <a href="#" aria-label="Next">
  16. <span aria-hidden="true">下一页</span>
  17. </a>
  18. </li>
  19. </ul>
  20. </nav>

那么这个时候咱们再去浏览器刷新的时候,就可以看到效果,当然,这些标签点击了也是没有任何作用的:

接下来咱们需要对每个li设置动作;

有多少页就设置多少个li

因为咱们直接引用的bootstrap组件就只有5个,所以我们有多少页就需要设置多少给li标签:

  1. #
  2. {% for item in paginator.page_range %}
  3. <li><a href="?page={{ item }}">{{ item }}</a></li>
  4. {% endfor %}

首先这个paginator是一个分页器对象,然后呢page_range表示的页码的列表,那么我们对这个进行循环的话,就可以做到有多少页就设置多少个li标签了。

这里是浏览器刷新后的效果:

然后当我们点击这1-10就可以实现跳转了:

现在呢是完成了这个标签的,但是我们发现没有,你点击了5然后跳转到了第5页,你从请求url中看到了这是第5页,但是这个li标签却看不出来,所以我们还需要将点击的Li标签加一个class:

为点击的li标签添加class样式

咱们在views视图中获取到了每一页的页码current_page_num,然后我们在模板中也拿到了页码item,那么我们如果让这两个值相同的话,就给它加一个样式:

  1. {% for item in paginator.page_range %}
  2. {% if current_page_num == item %}
  3. <li class="active"><a href="?page={{ item }}">{{ item }}</a></li>
  4. {% else %}
  5. <li><a href="?page={{ item }}">{{ item }}</a></li>
  6. {% endif %}
  7. {% endfor %}

下面是浏览器上看到的效果

上一页和下一页

因为咱们的上一页和下一页是没有进行设置的,所以点击是没有进行任何跳转的。

首先解决咱们的下一页,思路是这样的:比如我们现在在第9页上,对第九页进行判断,如果存在下一页那就跳转到下一页去,如果没有,那么这个li标签就不能跳转,即给他禁止:

  1. # 下一页
  2. {% if current_page.has_next %}
  3. <li>
  4. <a href="?page={{ current_page.next_page_number }}" aria-label="Next">
  5. <span aria-hidden="true">下一页</span>
  6. </a>
  7. </li>
  8. {% else %}
  9. <li class='disabled'>
  10. <a href="#" aria-label="Next">
  11. <span aria-hidden="true">下一页</span>
  12. </a>
  13. </li>
  14. {% endif %}

看一下效果图:

那么同理,上一页也是这样做到的:

  1. # 上一页
  2. {% if current_page.has_previous %}
  3. <li>
  4. <a href="#" aria-label="Previous">
  5. <span aria-hidden="true">上一页</span>
  6. </a>
  7. </li>
  8. {% else %}
  9. <li class="disabled">
  10. <a href="#" aria-label="Previous">
  11. <span aria-hidden="true">上一页</span>
  12. </a>
  13. </li>
  14. {% endif %}

当到了第一页的时候,就不能点击上一页了。

扩展知识点

首先让我们看一下现象

如果领导吩咐每一页只显示5行数据的话,那么就会有20页,那么如果一页就显示2条数据的话呢?所以这些肯定是不合理的,咱们需要根据这个页码进行修改:

  1. current_page_num = int(request.GET.get('page', 1)) # 显示第一页的页码
  2. if paginator.num_pages > 11: # 如果总页数大于19,就进入到这个判断中
  3. if current_page_num-5 < 1: # 如果当前所在的页数减去5页小于1
  4. page_range = range(1, 11) # 那么页码的范围就是1-11
  5. elif current_page_num+5 > paginator.num_pages: # 如果当前页数+5大于总页数
  6. page_range = range(paginator.num_pages-11, paginator.num_pages+1) # 那么此时页码的范围就是总页数减去11到总页码+1
  7. else:
  8. page_range = page_range = range(current_page_num-5, current_page_num+5) # 其余情况就显示在中间
  9. else:
  10. page_range = paginator.page_range

当咱们的请求发过去,只有两种情况:

1.总页数大于11

2.总页数小于11

如果小于11的话,那么就走下面的else,如果页数大于11,那么就走上面的条件判断,此时的条件判断分为三种情况(因为我们想让这个页码一直显示在中间):

1.如果当前页码减去5页的话小于1页,那么此时页码的范围就是1-11

2.如果当前页码加上5页大于总页数的话,那么此时的页码范围就是当前页数减去11页到当前页数加上1页之间,左合右开

3.如果都不符合,那么就显示在中间

那么此时刷新浏览器就能看到:

第一种情况:

第二种情况:

第三种情况:

那么此时咱们就完成了分页器。

django中的分页器组件的更多相关文章

  1. Django中的form组件

    Django中的form组件有两大作用 1.验证获取正确的结果或者错误信息 2.生成html代码 一.为什么需要form组件呢? 在写form表单,提交数据时,自己写验证的代码是一件非常困难的事情. ...

  2. django中的forms组件

    form介绍 用户需要向后端提交一些数据时,我们常常把这些数据放在一个form表单里,采用form标签,里面包含一些input等标签把用户的数据提交给后端. 在给后端提交数据的时候,我们常常也需要对于 ...

  3. django中的ajax组件

    目录 django中的ajax 向服务器发送请求的途径 Ajax的特点 基于jquery实现的ajax请求 利用ajax实现计算器 利用ajax实现登陆认证 利用form表单进行文件上传 利用ajax ...

  4. (31)django中的分页器

    book_list = models.Book.objects.all()    #查出指定表中的所有数据paginator = Paginator(book_list,2)    #实例化对象,传入 ...

  5. django中使用Form组件

    内容: 1.Form组件介绍 2.Form组件常用字段 3.Form组件校验功能 4.Form组件内置正则校验 参考:https://www.cnblogs.com/liwenzhou/p/87478 ...

  6. django中的forms组件(权限信息校验,增删改查)

    1.用处 1.用户请求数据验证 2.自动生成错误信息 3.打包用户提交的正确信息 4.如果其中有一个错误了,其他的正确,则保留上次输入的内容 5.自动创建input标签并可以设置样式 6.基于form ...

  7. Pyhon之Django中的Form组件

    Pyhon之Django中的Form组件   新手上路 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面 ...

  8. Django中的admin组件分析

    admin的使用介绍 django-admin的使用 Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.可以在项目的 setting ...

  9. Flask-wtforms类似django中的form组件

    一.安装 pip3 install wtforms 二.简单使用 1.创建flask对象 from flask import Flask, render_template, request, redi ...

随机推荐

  1. bootstrap在ie8下,兼容媒体查询

    最近使用bootstrap做网站的时候发现,在ie8下的媒体查询一直失效: 后来解决了,做如下记录: 1.必须运行在服务器下 2.hack 条件语法,如下: <!--[if lte ie 9]& ...

  2. bugfree 数据库配置 显示No such file or directory

    把数据库服务器  localhost   改成127.0.0.1 sudo vi /etc/hosts 增加: 127.0.0.1   localhost 127.0.0.1   你的hostname ...

  3. Could NOT find SDL (missing: SDL_LIBRARY SDL_INCLUDE_DIR)

    sudo apt-get install libsdl-dev或 sudo apt-get install libsdl1.2-dev

  4. 小米笔记本 air 12.5寸 支持硬盘参数

    M.2接口 2280规格 单面芯片固态硬盘 PCIE协议

  5. Jmeter 中Cookie管理器的使用

    Jmeter中有好几个地方可以管理Cookie,比如 Http Cookie Manager HTTP Header Manager jmeter.property文件中: #CookieManage ...

  6. STL_算法_02_排序算法

    ◆ 常用的排序算法: 1.1.合并(容器A(全部/部分)&容器B(全部/部分)==>容器C(全部/部分),容器C中元素已经排好顺序),返回的值==>iteratorOutBegin ...

  7. RabbitMQ入门_07_Fanout 与 Topic

    A. 用广播的方式实现发布订阅 参考资料:https://www.rabbitmq.com/tutorials/tutorial-three-java.html Fanout 类型的 Exchange ...

  8. The Front-End Checklist

    做个记录,摘自Front-End Performance Checklist HTML Minified HTML: The HTML code is minified, comments, whit ...

  9. Short Encoding of Words

    2018-07-02 09:48:48 问题描述: 问题求解: 方法一.问题给了规模n = 2000,也就是说用BF在O(n^2)的时间复杂度可以过,因此,第一个方法就是BF,但是需要注意的是这里已经 ...

  10. English trip -- VC(情景课)1 C What's your name?

    Grammar focus 语法点 What's your name? What's his name? What her name? My name is Angela. His name is K ...