You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Strawberry Django默认分页:非Relay场景下是否有更简洁实现方案?

问题描述

根据Strawberry Django官方文档及相关Issue,该库既未提供默认分页机制,也不会对查询结果设置最大返回条数限制。我已通过自定义field_cls实现了默认分页逻辑,代码如下:

PAGINATION_MAX_LIMIT = 1000

class DefaultPaginationStrawberryDjangoField(StrawberryDjangoField):

    def apply_pagination(self, queryset, pagination=None):
        if pagination is None:
            pagination = OffsetPaginationInput()
        if pagination.limit > PAGINATION_MAX_LIMIT or pagination.limit == -1:
            pagination.limit = PAGINATION_MAX_LIMIT
        return super().apply_pagination(queryset, pagination)


@strawberry.django.type(Project, pagination=True)
class ProjectType: 
  ...

@strawberry.type
class Query:
    projects: list[ProjectType] = strawberry.django.field(field_cls=DefaultPaginationStrawberryDjangoField)

由于不想使用Relay风格分页,请问有没有更优、更简洁的实现方式?

更简洁的实现方案

方案1:全局统一配置(无需逐个字段指定)

通过替换默认的strawberry.django.field实现全局生效,避免每个查询字段都手动指定field_cls:

from strawberry import django as strawberry_django
from strawberry_django.fields import StrawberryDjangoField
from strawberry_django.pagination import OffsetPaginationInput

PAGINATION_MAX_LIMIT = 1000

class DefaultPaginationField(StrawberryDjangoField):
    def apply_pagination(self, queryset, pagination=None):
        # 无分页参数时默认启用分页
        if pagination is None:
            pagination = OffsetPaginationInput()
        # 限制最大条数,处理-1(无限制)的情况
        pagination.limit = PAGINATION_MAX_LIMIT if pagination.limit == -1 or pagination.limit > PAGINATION_MAX_LIMIT else pagination.limit
        return super().apply_pagination(queryset, pagination)

# 全局替换默认字段类
original_django_field = strawberry_django.field
strawberry_django.field = lambda **kwargs: original_django_field(field_cls=DefaultPaginationField, **kwargs)

之后所有使用strawberry.django.field定义的查询字段都会自动应用该分页逻辑,无需额外配置。

方案2:复用性更高的Mixin写法

如果不需要全局生效,仅需给部分字段添加分页逻辑,可以用Mixin类封装分页逻辑,后续需要时直接组合即可:

from strawberry_django.fields import StrawberryDjangoField
from strawberry_django.pagination import OffsetPaginationInput

PAGINATION_MAX_LIMIT = 1000

class DefaultPaginationMixin:
    def apply_pagination(self, queryset, pagination=None):
        if pagination is None:
            pagination = OffsetPaginationInput()
        pagination.limit = min(pagination.limit, PAGINATION_MAX_LIMIT) if pagination.limit != -1 else PAGINATION_MAX_LIMIT
        return super().apply_pagination(queryset, pagination)

# 组合Mixin与原字段类
class DefaultPaginationStrawberryDjangoField(DefaultPaginationMixin, StrawberryDjangoField):
    pass

使用时依然在需要的字段上指定field_cls=DefaultPaginationStrawberryDjangoField即可,但Mixin的写法更便于后续扩展其他通用逻辑。

代码简化技巧

可以将分页限制的判断逻辑简化为一行代码,让代码更紧凑:

pagination.limit = PAGINATION_MAX_LIMIT if pagination.limit in (-1, None) or pagination.limit > PAGINATION_MAX_LIMIT else pagination.limit

内容的提问来源于stack exchange,提问作者fabien-michel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 05:12:46