前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python进阶31-Django 分页器

Python进阶31-Django 分页器

作者头像
DriverZeng
发布2022-09-26 12:43:00
1.6K0
发布2022-09-26 12:43:00
举报
文章被收录于专栏:Linux云计算及前后端开发

-曾老湿, 江湖人称曾老大。


-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。


分页器


分页器介绍

介绍个p啊,不就是一堆数据不放在一页显示,放在好几页嘛...

具体长啥样?每个网站都不一样...

大概就是 ... 这样

在页面显示分页数据,需要用到Django分页器组件


导入分页模块

代码语言:javascript
复制
from django.core.paginator import Paginator

Paginator对象:    paginator = Paginator(user_list, 10)
# per_page: 每页显示条目数量
# count:    数据总个数
# num_pages:总页数
# page_range:总页数的索引范围,如: (1,10),(1,200)
# page:     page对象    
page对象:page=paginator.page(1)
# has_next              是否有下一页
# next_page_number      下一页页码
# has_previous          是否有上一页
# previous_page_number  上一页页码
# object_list           分页之后的数据列表
# number                当前页
# paginator             paginator对象

话不多说...写他*的


创建项目

连接数据库创建表,直接使用sqllite数据库

代码语言:javascript
复制
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

创建一张表,往里面多写点数据,然后我们才好分页

代码语言:javascript
复制
from django.db import models

# Create your models here.

class Book(models.Model):
    name  = models.CharField(max_length=32)
    price =  models.DecimalField(max_digits=5,decimal_places=2)

数据库迁移

代码语言:javascript
复制
MacBook-pro:fenye driverzeng$ python3 manage.py makemigrations app0
MacBook-pro:fenye driverzeng$ python3 manage.py migrate


批量插入数据

代码语言:javascript
复制
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
]
代码语言:javascript
复制
from django.shortcuts import render, HttpResponse

# Create your views here.
from app01 import models


def index(request):
    ## 以前写法
    # for i in range(100):
    #     models.Book.objects.create(name='图书%s' % i, price=10 + i)

    ## 现在写法(批量插入)
    # 1.先造出100本书,放到列表中
    l = []
    for i in range(100):
        l.append(models.Book(name='图书%s' % i, price=10 + i))

    # 批量插入,第一个参数插入的对象,第二个参数,每一次插入多少条(不写则全插)
    models.Book.objects.bulk_create(l, 10)

    return HttpResponse('ok')

一访问页面,100条数据就进去了。

现在写index页面,返回数据

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图书 分页</title>
</head>
<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">
<body>
<div class="container-fluid">
    <nav class="navbar navbar-default navbar-inverse">
        <div class="container-fluid">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                        data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">图书管理系统</a>
            </div>
            <!-- Collect the nav links, forms, and other content for toggling -->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <form class="navbar-form navbar-left">
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="你要找啥啊?">
                    </div>
                    <button type="submit" class="btn btn-default">搜索图书</button>
                </form>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <table class="table table-hover">
                <thead>
                <tr>
                    <th>书名</th>
                    <th>价格</th>
                </tr>
                </thead>
                <tbody>
                {% for book in book_list %}
                    <tr>
                        <td>{{ book.name }}</td>
                        <td>{{ book.price }}</td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>


添加前端分页

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图书 分页</title>
</head>
<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">
<body>
<div class="container-fluid">
    <nav class="navbar navbar-default navbar-inverse">
        <div class="container-fluid">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                        data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">图书管理系统</a>
            </div>
            <!-- Collect the nav links, forms, and other content for toggling -->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <form class="navbar-form navbar-left">
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="你要找啥啊?">
                    </div>
                    <button type="submit" class="btn btn-default">搜索图书</button>
                </form>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <table class="table table-hover">
                <thead>
                <tr>
                    <th>书名</th>
                    <th>价格</th>
                </tr>
                </thead>
                <tbody>
                {% for book in book_list %}
                    <tr>
                        <td>{{ book.name }}</td>
                        <td>{{ book.price }}</td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
            <nav aria-label="Page navigation">
                <ul class="pagination">
                    <li>
                        <a href="#" aria-label="Previous">
                            <span aria-hidden="true">上一页</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">下一页</span>
                        </a>
                    </li>
                </ul>
            </nav>
        </div>
    </div>
</div>
</body>
</html>

Django分页器使用

代码语言:javascript
复制
from django.shortcuts import render, HttpResponse

# Create your views here.
from app01 import models
from django.core.paginator import Paginator   # 导入分页器的类

def index(request):
    book_list = models.Book.objects.all()
    # 实例化产生一个对象
    ## 两个参数
    # 1.第一个是对象列表
    # 2.第二个是每页的条数
    paginator=Paginator(book_list,10)

    ## 数据总条数
    print(paginator.count)

    ## 总页数 (10页)
    print(paginator.num_pages)

    ## 页码数列表
    print(paginator.page_range)

    ## 取到第x页,返回一个对象
    current_page = paginator.page(5)

    ## 当前页面的数据
    print(current_page.object_list)

    ## 是否有下一页
    print(current_page.has_next())

    ## 是否有上一页
    print(current_page.has_previous())

    ## 下一页页码数
    print(current_page.next_page_number())

    ## 上一页页码数
    print(current_page.previous_page_number())

    return render(request,'index.html',locals())

代码语言:javascript
复制
from django.shortcuts import render, HttpResponse

# Create your views here.
from app01 import models
from django.core.paginator import Paginator   # 导入分页器的类

def index(request):
    book_list = models.Book.objects.all()

    paginator = Paginator(book_list, 10)
    current_page_num = int(request.GET.get('page'))
    current_page = paginator.page(current_page_num)

    ## 当前页码所有数据
    print(current_page.object_list)
    # 既可以循环 current_page.pbject_list,又可以循环当前页的对象
    for item in current_page:
        print(item.name)
    return render(request, 'index.html', locals())

目前只能通过浏览器传递数据,查看到后台内容,现在去修改前端。

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图书 分页</title>
</head>
<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">
<body>
<div class="container-fluid">
    <nav class="navbar navbar-default navbar-inverse">
        <div class="container-fluid">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                        data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">图书管理系统</a>
            </div>
            <!-- Collect the nav links, forms, and other content for toggling -->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <form class="navbar-form navbar-left">
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="你要找啥啊?">
                    </div>
                    <button type="submit" class="btn btn-default">搜索图书</button>
                </form>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <table class="table table-hover">
                <thead>
                <tr>
                    <th>书名</th>
                    <th>价格</th>
                </tr>
                </thead>
                <tbody>
                {% for book in current_page %}
                    <tr>
                        <td>{{ book.name }}</td>
                        <td>{{ book.price }}</td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
            <nav aria-label="Page navigation">
                <ul class="pagination">
                    {% if current_page.has_previous %}
                        <li>
                            {#<a href="/index/?page={{ current_page_num|add:-1 }}" aria-label="Previous">#}
                            <a href="/index/?page={{ current_page.previous_page_number }}" aria-label="Previous">
                                <span aria-hidden="true">上一页</span>
                            </a>
                        </li>
                    {% else %}
                        <li class="disable">
                            {#<a href="/index/?page={{ current_page_num|add:-1 }}" aria-label="Previous">#}
                            <a href="" aria-label="Previous">
                                <span aria-hidden="true">上一页</span>
                            </a>
                        </li>
                    {% endif %}

                    {% for total_page in paginator.page_range %}
                        {% if current_page_num == total_page %}
                            <li class="active"><a href="/index/?page={{ total_page }}">{{ total_page }}</a></li>
                        {% else %}
                            <li><a href="/index/?page={{ total_page }}">{{ total_page }}</a></li>
                        {% endif %}
                    {% endfor %}
                    {% if current_page.has_next %}
                        <li>
                            <a href="/index/?page={{ current_page.next_page_number }}" aria-label="Next">
                                <span aria-hidden="true">下一页</span>
                            </a>
                        </li>
                    {% else %}
                        <li class="disable">
                            <a href="" aria-label="Next">
                                <span aria-hidden="true">下一页</span>
                            </a>
                        </li>
                    {% endif %}
                </ul>
            </nav>
        </div>
    </div>
</div>
</body>
</html>

终极分页器使用

刚才的代码是有bug的,我们来解决一下bug,如果我们手动改浏览器中的?page=100000000,程序就炸了。Boom~~~~~~

不管输入多少,都跳转到最后一页

代码语言:javascript
复制
from django.shortcuts import render, HttpResponse

# Create your views here.
from app01 import models
from django.core.paginator import Paginator,EmptyPage   # 导入分页器的类

def index(request):
    book_list = models.Book.objects.all()
    paginator = Paginator(book_list, 10)
    try:
        current_page_num = int(request.GET.get('page'))
        current_page = paginator.page(current_page_num)
    ## 当前页码所有数据
    # print(current_page.object_list)
    # 既可以循环 current_page.pbject_list,又可以循环当前页的对象
    # for item in current_page:
    #     print(item.name)
    except EmptyPage as e:
        # 捕获异常后跳转到最后一页
        current_page_num = paginator.num_pages
        current_page = paginator.page(current_page_num)
    return render(request, 'index.html', locals())

但是还tmd有bug,我们在后端用int转了数据,但是如果调皮的用户们,输入的是字母或者特殊符号,int没有办法转...程序还是会炸。

继续捕获异常

代码语言:javascript
复制
from django.shortcuts import render, HttpResponse

# Create your views here.
from app01 import models
from django.core.paginator import Paginator,EmptyPage   # 导入分页器的类

def index(request):
    book_list = models.Book.objects.all()
    paginator = Paginator(book_list, 10)
    try:
        current_page_num = int(request.GET.get('page'))
        current_page = paginator.page(current_page_num)
    ## 当前页码所有数据
    # print(current_page.object_list)
    # 既可以循环 current_page.pbject_list,又可以循环当前页的对象
    # for item in current_page:
    #     print(item.name)
    except Exception as e:
        # 捕获异常后跳转到最后一页
        current_page_num = paginator.num_pages
        current_page = paginator.page(current_page_num)
    return render(request, 'index.html', locals())

现在bug是没有了,但是还有一个问题 ... 我们现在网页显示的是10条,10条的话,看起来还阔以噻~

但是如果我们每页显示3条咋整?感受一下?

尼玛~ 丑的不要不要的啊。改tmd

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图书 分页</title>
</head>
<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">
<body>
<div class="container-fluid">
    <nav class="navbar navbar-default navbar-inverse">
        <div class="container-fluid">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                        data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">图书管理系统</a>
            </div>
            <!-- Collect the nav links, forms, and other content for toggling -->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <form class="navbar-form navbar-left">
                    <div class="form-group">
                        <input type="text" class="form-control" placeholder="你要找啥啊?">
                    </div>
                    <button type="submit" class="btn btn-default">搜索图书</button>
                </form>
            </div><!-- /.navbar-collapse -->
        </div><!-- /.container-fluid -->
    </nav>
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <table class="table table-hover">
                <thead>
                <tr>
                    <th>书名</th>
                    <th>价格</th>
                </tr>
                </thead>
                <tbody>
                {% for book in current_page %}
                    <tr>
                        <td>{{ book.name }}</td>
                        <td>{{ book.price }}</td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
            <nav aria-label="Page navigation">
                <ul class="pagination">
                    {% if current_page.has_previous %}
                        <li>
                            {#<a href="/index/?page={{ current_page_num|add:-1 }}" aria-label="Previous">#}
                            <a href="/index/?page={{ current_page.previous_page_number }}" aria-label="Previous">
                                <span aria-hidden="true">上一页</span>
                            </a>
                        </li>
                    {% else %}
                        <li class="disabled">
                            {#<a href="/index/?page={{ current_page_num|add:-1 }}" aria-label="Previous">#}
                            <a href="" aria-label="Previous">
                                <span aria-hidden="true">上一页</span>
                            </a>
                        </li>
                    {% endif %}

                    {% for total_page in page_range %}
                        {% if current_page_num == total_page %}
                            <li class="active"><a href="/index/?page={{ total_page }}">{{ total_page }}</a></li>
                        {% else %}
                            <li><a href="/index/?page={{ total_page }}">{{ total_page }}</a></li>
                        {% endif %}
                    {% endfor %}
                    {% if current_page.has_next %}
                        <li>
                            <a href="/index/?page={{ current_page.next_page_number }}" aria-label="Next">
                                <span aria-hidden="true">下一页</span>
                            </a>
                        </li>
                    {% else %}
                        <li class="disabled">
                            <a href="" aria-label="Next">
                                <span aria-hidden="true">下一页</span>
                            </a>
                        </li>
                    {% endif %}

                </ul>
            </nav>
        </div>
    </div>
</div>
</body>
</html>
代码语言:javascript
复制
from django.shortcuts import render, HttpResponse

# Create your views here.
from app01 import models
from django.core.paginator import Paginator,EmptyPage   # 导入分页器的类

def index(request):
    book_list = models.Book.objects.all()
    paginator = Paginator(book_list, 3)
    # 如果页码数多,让他显示前五,后五,中间是当前在的页码
    try:
        current_page_num = int(request.GET.get('page'))
        page_range = range(current_page_num - 5, current_page_num + 6)
        current_page = paginator.page(current_page_num)
    except Exception as e:
        current_page_num = paginator.num_pages
        current_page = paginator.page(current_page_num)
    return render(request, 'index.html', locals())

诶?看起来好像是可以了。。。。。可以个锤子哦。

请看下图...这特么的是啥?

代码语言:javascript
复制
from django.shortcuts import render, HttpResponse

# Create your views here.
from app01 import models
from django.core.paginator import Paginator,EmptyPage   # 导入分页器的类

def index(request):
    book_list = models.Book.objects.all()
    paginator = Paginator(book_list, 3)
    # 如果页码数多,让他显示前五,后五,中间是当前在的页码
    try:
        current_page_num = int(request.GET.get('page'))
        current_page = paginator.page(current_page_num)
    except Exception as e:
        current_page_num = 1
        current_page = paginator.page(current_page_num)
    if paginator.num_pages > 11:
        if current_page_num - 5 < 1:
            page_range = range(1, 12)
        elif current_page_num + 5 > paginator.num_pages:
            page_range = range(paginator.num_pages - 11, paginator.num_pages + 1)
        else:
            page_range = range(current_page_num - 5, current_page_num + 6)
    else:
        page_range = paginator.page_range
    return render(request, 'index.html', locals())

前端使用ajax后端写成装饰器

代码语言:javascript
复制
from django.shortcuts import render, HttpResponse

# Create your views here.
from app01 import models
from django.core.paginator import Paginator,EmptyPage   # 导入分页器的类

import json
def auth_ajax(func):
    def inner(request,*args,**kwargs):
        request.data = request.POST
        try:
            request.data = json.loads(request.body.decode('utf-8'))
        except Exception as e:
            print(e)
        res = func(request,*args,**kwargs)
        return res
    return inner


@auth_ajax
def index(request):
    if request.method == 'GET':
        return render(request,'index.html')
    elif request.method == 'POST':
        print(request.data)
        return HttpResponse('OK')
代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图书分页AJAX</title>
</head>
<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">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<body>
    <button id="btn">点我</button>
    <script>
        $('#btn').click(function () {
            var dic = {'name':'zls'}
            var da = JSON.stringify(dic)
            $.ajax({
                url: '/index/',
                type: 'post',
                contentType: 'application/json',
                data:da,
                success:function (data) {
                    console.log(data)
                }
            })
        })
    </script>
</body>
</html>

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-04-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 分页器
  • 话不多说...写他*的
  • Django分页器使用
  • 终极分页器使用
  • 前端使用ajax后端写成装饰器
相关产品与服务
运维安全中心(堡垒机)
腾讯云运维安全中心(堡垒机)(Operation and Maintenance Security Center (Bastion Host))可为您的 IT 资产提供代理访问以及智能操作审计服务,为客户构建一套完善的事前预防、事中监控、事后审计安全管理体系,助力企业顺利通过等保测评。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档