【Django-ninja】分页管理器

django ninja通过@paginate装饰器即可进行分页。内置了两个分页管理器LimitOffsetPagination和PageNumberPagination,能够实现基本的分页要求。当内置分页器不满足要求时,可以继承PaginationBase进行扩展自己的分页管理器。

1 使用分页器

python 复制代码
from ninja.pagination import paginate

@api.get('/users', response=List[UserSchema])
@paginate
def list_users(request):
    return User.objects.all()

/api/users?limit=10&offset=0

返回:

python 复制代码
{
"items": [],
"count": 10
}

2 ninja自带分页器

2.1 LimitOffsetPagination

默认paginate使用的就是该分页器。

2.2 PageNumberPagination

python 复制代码
@api.get("/users")
@paginate(PageNumberPagination, page_size=50)
def list_users(...

返回结果包含items和count

python 复制代码
{
"items": [],
"count": 10
}

2.3 自定义分页器

这个自定义分页器定义了Input、Output、paginate_queryset。

实现了page和page_size参数获取数据。page_size可以通过多种方式进行调节。在定义接口的时候设置固定值,或者使用分页器的默认值,或者使用用户的传输参数。

返回结果,新增多个字段,修改默认items为data。

python 复制代码
#!/usr/bin/env python
# coding=utf-8
# @Time    : 2024/2/2 15:40
# @Software: PyCharm
import math
from ninja import Schema
from ninja.pagination import PaginationBase
from typing import List, Any, Optional


class CustomPagination(PaginationBase):

    def __init__(self, page_size: Optional[int] = None, **kwargs):
        """ 如果指定具体值,那么用户参数中的page_size将会失效。
        page_size: 在定义接口是可以设置的每页记录数。

        例如:
        @api.get("/book")
        @paginate(CustomPagination)
        def book_list(request):
            return Book.objects.all()

        @api.get("/book")
        @paginate(CustomPagination, page_size=10)  # 定义接口默认每页数量
        def book_list(request):
            return Book.objects.all()

        """
        self.page_size = page_size
        super().__init__(**kwargs)

    class Input(Schema):
        """ 输入参数,两个参数。
            1. page(必须
            2. page_size(可选)
        """
        page: int
        page_size: int = 5

    class Output(Schema):
        """输出结果。
            1. data 数据集合
            2. total:总记录数
            3. per_page:每页记录数
            4. total_page:总页数
            5. page:当前页
        """
        data: List[Any]  # <--- data
        total: int
        per_page: int
        total_page: int
        page: int

    def paginate_queryset(self, queryset, pagination: Input, **params):
        page = pagination.page
        page_size = self.page_size or pagination.page_size
        start_idx = (page - 1) * page_size
        end_idx = start_idx + page_size
        total_count = queryset.count()
        return {
            'data': queryset[start_idx: end_idx],  # <--- data
            'total': total_count,
            'per_page': page_size,
            'total_page': math.ceil(total_count / page_size),
            'page': page
        }

    items_attribute: str = "data"  # <--- 将默认数据集合的名称从items修改成data
相关推荐
正在走向自律几秒前
RSA加密从原理到实践:Java后端与Vue前端全栈案例解析
java·前端·vue.js·密钥管理·rsa加密·密钥对·aes+rsa
xwz小王子11 分钟前
ManipulationNet:开启真实世界机器人操作基准测试新时代
数据库·机器人
咯哦哦哦哦18 分钟前
关于QT 打印中文 乱码问题
java·数据库·qt
爱读源码的大都督26 分钟前
天下苦@NonNull久矣,JSpecify总算来了,Spring 7率先支持!
java·后端·架构
木头没有瓜40 分钟前
Slf4j 接口文档左侧菜单有显示,但是点击后空白
java
野犬寒鸦41 分钟前
从零起步学习Redis || 第十二章:Redis Cluster集群如何解决Redis单机模式的性能瓶颈及高可用分布式部署方案详解
java·数据库·redis·后端·缓存
ShooterJ1 小时前
Mysql小表驱动大表优化原理
数据库·后端·面试
程序员三明治1 小时前
【MyBatis从入门到入土】告别JDBC原始时代:零基础MyBatis极速上手指南
数据库·mysql·mybatis·jdbc·数据持久化·数据
cxyxiaokui0011 小时前
还在用 @Autowired 字段注入?你可能正在写出“脆弱”的 Java 代码
java·后端·spring
闲人编程1 小时前
将你的Django/Flask应用部署到云服务器(Docker实战)
服务器·docker·容器·django·flask·部署·web