Python进阶31-Django 分页器

2022-09-26 12:43:00 浏览数 (1)

  • 分页器
  • 话不多说...写他*的
  • Django分页器使用
  • 终极分页器使用
  • 前端使用ajax后端写成装饰器

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


-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长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>

0 人点赞