分页

Oasis 提供了对 Django QuerySet 对象进行分页的方法,仅需 2 行代码即可实现数据分页。

内置分页器

下面的示例将对 Book 模型实现 2 种分页查询方式。

models.py [示例1]
from django.db import models


class Book(models.Model):
    title = models.CharField(max_length=10, verbose_name="书名")
    author = models.CharField(max_length=20, verbose_name="作者")

PagePagination

page_pagination.py [示例1]
from django.db import models

from django_oasis.common import model2schema
from django_oasis.core import Resource
from django_oasis.pagination import PagePagination

from .models import Book


@Resource("/books/page")
class BookListAPI:
    def get(
        self,
        pagination=PagePagination(model2schema(Book)),  # 设置分页器
    ):
        return pagination.paginate(Book.objects.all())  # 使用分页器

OffsetPagination

offset_pagination.py [示例1]
from django.db import models

from django_oasis.common import model2schema
from django_oasis.core import Resource
from django_oasis.pagination import OffsetPagination

from .models import Book


@Resource("/books/offset")
class BookListAPI:
    def get(
        self,
        pagination=OffsetPagination(model2schema(Book)),  # 设置分页器
    ):
        return pagination.paginate(Book.objects.all())  # 使用分页器

警告

使用分页器时,无需为 Operation 设置 response_schema 参数,分页器在设置时会自动为其填充。

SwaggerUI [示例1]

自定义分页器

分页器是高度可定制的,只需继承 django_oasis.pagination.Pagination 抽象类,并实现其抽象方法。

views.py [示例2]
from django.db import models

from django_oasis import schema
from django_oasis.common import model2schema
from django_oasis.core import Resource
from django_oasis.pagination import Pagination
from django_oasis.parameter import Query


class Book(models.Model):
    title = models.CharField(max_length=10, verbose_name="书名")
    author = models.CharField(max_length=20, verbose_name="作者")


class BookSchema(model2schema(Book)):
    pass


class MyPagination(Pagination):
    def __init__(self, item_schema):
        # 初始化时,需要提供分页项目的schema
        self._item_schema = item_schema

    def _get_request_parameter(self):
        # 该方法是告诉分页器从哪里获取请求参数。
        # 获取到的参数会传给 `_get_response`。
        return Query(
            {
                "page": schema.Integer(
                    default=1, minimum=1, alias="p", description="页码"
                ),
                "page_size": schema.Integer(
                    default=20, minimum=1, alias="size", description="页面大小"
                ),
            }
        )

    def _get_response_schema(self):
        # 该方法为所在 Operation 设置 response_schema

        class ResponseSchema(schema.Model):
            data = schema.List(self._item_schema, description="数据列表")
            total = schema.Integer(description="数据总数")

        return ResponseSchema()

    def _get_response(self, queryset, reqarg):
        # 返回请求响应。
        page, page_size = reqarg["page"], reqarg["page_size"]
        offset = (page - 1) * page_size

        # 无需手动序列化,因为已经实现了 `_get_response_schema` 方法。
        return {
            "items": queryset[offset : offset + page_size],
            "total": queryset.count(),
        }


@Resource("/books")
class BookListAPI:
    def get(self, pagination=MyPagination(BookSchema)):
        return pagination.paginate(Book.objects.all())
SwaggerUI [示例2]