首页Django

Django 数据分页功能

2020年10月9日 10:41529

Paginator类

Paginator类的作用是将数据分割成若干份,在前端以分页的形式展示。当我们实例化一个Paginator类,需要给Paginator传递两个参数。第一个参数是数据源,可以是列表、元组以及查询结果集QuerySet。第二个参数传递一个整数,表示每夜显示的数据数量。

# Paginator基本写法

data_list = Book_all.objects.all() # 假定data_list获取数据库中的信息
paginator = Paginator(data_list,10)  # data_list为数据源,每页显示10条数据

Paginator类有三个常用的属性:

count:所有页面的对象总数

num_pages:页面总数

page_range:下表从1开始的页数范围迭代器

Page对象

Paginator类提供一个**page(number)**函数,该函数返回一个Page对象。参数number表示第几个分页,如果number=1,那么page()返回的对象是第一分页的Page对象。在前端页面中显示数据,主要都是基于Page对象。

# 使用paginator对象返回第一页的page对象

books = paginator.page(1)

Page对象有三个常用属性:

object_list:当前页面上所有对象的列表

numberv:当前页的序号,从1开始计数

paginator:当前Page对象所属的Paginator对象

Page对象还有几个常用的函数:

has_next():判断是否还有下一页,有的话返回True

has_previous():判断是否还有上一页,有的话返回True

has_other_pages():判断是否上一页或下一页,有的话返回True

next_page_number():返回下一页的页码,如果不存在,抛出InvalidPage异常

previous_page_number():返回上一页的页码,如果不存在,抛出InvalidPage异常

应用案例

下面是自己编写的Demo程序,介绍Paginator和Page的基本使用。先创建基本的Model模型数据,在View中获取需要展示的全部数据,然后使用Paginator类对数据进行分页,最后返回第1个页面的page对象。page对象的作用很大,一方面显示当前分页数据,还提供获取后续页面数据的接口。

# models.py

from django.db import models


class Book(models.Model):
    """图书模型"""
    title = models.CharField('图书',max_length=64)
    price = models.CharField('价格',max_length=32)
    pub_date = models.DateField('出版日期',auto_now_add=True)

    class Meta:
        verbose_name = '图书'
        verbose_name_plural = '图书管理'

    def __str__(self):
        return self.title
# views.py

from django.shortcuts import render,redirect
from book.models import Book
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger


def book_list(request):
    """图书管理"""
    book_all = Book.objects.all()  # 获取book表中的所有数据
    # 分页功能
    paginator = Paginator(book_all,10)  # 实例化一个Paginator,设置每页显示10条数据
    page = request.GET.get('page')  # 获取url后面page参数的值,首页不显示page参数, 默认值是1
    try:
        contacts = paginator.page(page)
    except PageNotAnInteger:
        contacts = paginator.page(1)  # 如果请求的页数不是整数,返回第一页
    except EmptyPage:
        contacts = paginator.page(paginator.num_pages)  # 如果请求的页数不在合法的页数范围内,返回结果的最后一页。
    context = {
        'contacts':contacts,
    }
    return render(request,'book_list.html',context)
# book_list.html

<!DOCTYPE HTML>
<html>

<head>
    <meta charset="utf-8" />
    <title>Django数据分页演示</title>
    <meta name="keywords" content="" />
    <meta name="description" content="" />
</head>

<body>
<table>
            <thead>
                <tr>
                    <th>编号</th>
                    <th>图书</th>
                    <th>价格</th>
                    <th>出版日期</th>
                </tr>
            </thead>
            <tbody>
                {% for books in contacts %}
                <tr>
                    <td>{{ forloop.counter }}</td>
                    <td>{{ books.title }}</td>
                    <td>{{ books.price }}</td>
                    <td>{{ books.pub_date }}</td>
                </tr>
                {% endfor %}
            </tbody>
        </table>

        <div class="pagination">
            {% for page_num in contacts.paginator.page_range %}
            <a {% if contacts.number == page_num %}class="active"{% endif %} href="?page={{ page_num }}">{{ page_num }}</a>
            {% endfor %}

            <a {% if contacts.has_previous %}href="?page={{ contacts.previous_page_number }}"{% endif %}>上一页</a>
            <a {% if contacts.has_next %}href="?page={{ contacts.next_page_number }}"{% endif %}>下一页</a>
            <span>页数:{{ contacts.number }}/{{ contacts.paginator.num_pages }}</span>
        </div>
</body>
</html>

拿到视图传递过来的contacts(contacts是一个Page对象),模版中使用contacts根据页面情况展示上一页、下一页、总页数、当前页码

运行结果

Django软件界面

封装代码

当使用分页功能的需求变多以后,封装代码就变得尤为重要了。新建一个page.py(名字和位置随意),自定义一个分页函数

# page.py

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger


def page_list(data_all,page,num):
    """数据分页"""
    paginator = Paginator(data_all, num)  # 实例化一个Paginator,data_all为数据源,num为每页显示数量
    try:
        contacts = paginator.page(page)
    except PageNotAnInteger:
        contacts = paginator.page(1)  # 如果请求的页数不是整数,返回第一页
    except EmptyPage:
        contacts = paginator.page(paginator.num_pages)  # 如果请求的页数不在合法的页数范围内,返回结果的最后一页。

    return contacts

在views.py中引用page.py中的page_list函数,并传入参数

# views.py

from django.shortcuts import render
from sales.models import Order
from apps.page import page_list  # 引用分页的自定义函数


def order(request):
    """销售订单-列表"""
    order_temp = Order.objects.all().order_by('-id')
    # 分页功能
    page = request.GET.get('page')  # 获取url后面page参数的值,首页不显示page参数, 默认值是1
    pages = page_list(order_temp, page, 10)

    context = {
        'pages':pages,
    }
    return render(request,'sales/sales.html',context)

前端新建一个page.html作公共分页模版,使用{% include 'page_list.html' %}来调用,这里注意:前端模版也是用pages变量来遍历数据。

# page_list.html

<div class="pagelist">
    {% for page_num in pages.paginator.page_range %}
    <a {% if pages.number == page_num %}class="current"{% endif %} href="?page={{ page_num }}">{{ page_num }}</a>
    {% endfor %}
    <a {% if pages.has_previous %}href="?page={{ pages.previous_page_number }}"{% endif %}>上一页</a>
    <a {% if pages.has_next %}href="?page={{ pages.next_page_number }}"{% endif %}>下一页</a>
    <span>页数:{{ pages.number }}/{{ pages.paginator.num_pages }}</span>
</div>