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
相关产品推荐
相关产品推荐

