From b081016c5a15206bb789c1d69e2fdfd12b72a528 Mon Sep 17 00:00:00 2001 From: Thiago Bellini Ribeiro Date: Sun, 15 Dec 2024 11:16:56 +0100 Subject: [PATCH 1/2] fix(pagination)!: Use `PAGINATION_DEFAULT_LIMIT` when limit is not provided --- strawberry_django/pagination.py | 28 ++++--- tests/projects/snapshots/schema.gql | 2 +- .../snapshots/schema_with_inheritance.gql | 2 +- tests/test_paginated_type.py | 74 ++++++++++++++++++- 4 files changed, 92 insertions(+), 14 deletions(-) diff --git a/strawberry_django/pagination.py b/strawberry_django/pagination.py index 1b6b4608..6ca9a699 100644 --- a/strawberry_django/pagination.py +++ b/strawberry_django/pagination.py @@ -13,6 +13,7 @@ from strawberry_django.fields.base import StrawberryDjangoFieldBase from strawberry_django.resolvers import django_resolver +from .settings import strawberry_django_settings from .arguments import argument @@ -22,16 +23,14 @@ PAGINATION_ARG = "pagination" -@strawberry.input -class OffsetPaginationInput: - offset: int = 0 - limit: Optional[int] = None - - @strawberry.type class OffsetPaginationInfo: offset: int = 0 - limit: Optional[int] = None + limit: Optional[int] = UNSET + + +@strawberry.input +class OffsetPaginationInput(OffsetPaginationInfo): ... @strawberry.type @@ -142,8 +141,13 @@ def apply( ) else: start = pagination.offset - if pagination.limit is not None and pagination.limit >= 0: - stop = start + pagination.limit + limit = pagination.limit + if limit is UNSET: + settings = strawberry_django_settings() + limit = settings["PAGINATION_DEFAULT_LIMIT"] + + if limit is not None and limit >= 0: + stop = start + limit queryset = queryset[start:stop] else: queryset = queryset[start:] @@ -165,7 +169,7 @@ def apply_window_pagination( *, related_field_id: str, offset: int = 0, - limit: Optional[int] = None, + limit: Optional[int] = UNSET, ) -> _QS: """Apply pagination using window functions. @@ -204,6 +208,10 @@ def apply_window_pagination( if offset: queryset = queryset.filter(_strawberry_row_number__gt=offset) + if limit is UNSET: + settings = strawberry_django_settings() + limit = settings["PAGINATION_DEFAULT_LIMIT"] + # Limit == -1 means no limit. sys.maxsize is set by relay when paginating # from the end to as a way to mimic a "not limit" as well if limit is not None and limit >= 0 and limit != sys.maxsize: diff --git a/tests/projects/snapshots/schema.gql b/tests/projects/snapshots/schema.gql index b5f31d33..26039d01 100644 --- a/tests/projects/snapshots/schema.gql +++ b/tests/projects/snapshots/schema.gql @@ -470,7 +470,7 @@ type OffsetPaginationInfo { input OffsetPaginationInput { offset: Int! = 0 - limit: Int = null + limit: Int } type OperationInfo { diff --git a/tests/projects/snapshots/schema_with_inheritance.gql b/tests/projects/snapshots/schema_with_inheritance.gql index 352c8e1b..2b11dd7d 100644 --- a/tests/projects/snapshots/schema_with_inheritance.gql +++ b/tests/projects/snapshots/schema_with_inheritance.gql @@ -248,7 +248,7 @@ type OffsetPaginationInfo { input OffsetPaginationInput { offset: Int! = 0 - limit: Int = null + limit: Int } type OperationInfo { diff --git a/tests/test_paginated_type.py b/tests/test_paginated_type.py index 0ae01892..db692c06 100644 --- a/tests/test_paginated_type.py +++ b/tests/test_paginated_type.py @@ -1,6 +1,7 @@ import textwrap from typing import Annotated +from django.test.utils import override_settings import pytest import strawberry from django.db.models import QuerySet @@ -8,6 +9,7 @@ import strawberry_django from strawberry_django.optimizer import DjangoOptimizerExtension from strawberry_django.pagination import OffsetPaginated, OffsetPaginationInput +from strawberry_django.settings import StrawberryDjangoSettings from tests import models @@ -69,7 +71,7 @@ class Query: input OffsetPaginationInput { offset: Int! = 0 - limit: Int = null + limit: Int } type Query { @@ -630,7 +632,7 @@ def fruits_with_order_and_filter(self) -> QuerySet[models.Fruit]: ... input OffsetPaginationInput { offset: Int! = 0 - limit: Int = null + limit: Int } type Query { @@ -900,3 +902,71 @@ def fruits_with_order_and_filter( ], }, } + + +@pytest.mark.django_db(transaction=True) +@override_settings( + STRAWBERRY_DJANGO=StrawberryDjangoSettings( # type: ignore + PAGINATION_DEFAULT_LIMIT=2, + ), +) +def test_pagination_default_limit(): + @strawberry_django.type(models.Fruit) + class Fruit: + id: int + name: str + + @strawberry.type + class Query: + fruits: OffsetPaginated[Fruit] = strawberry_django.offset_paginated() + + models.Fruit.objects.create(name="Apple") + models.Fruit.objects.create(name="Banana") + models.Fruit.objects.create(name="Strawberry") + models.Fruit.objects.create(name="Watermelon") + + schema = strawberry.Schema(query=Query) + + query = """\ + query GetFruits ($pagination: OffsetPaginationInput) { + fruits (pagination: $pagination) { + totalCount + results { + name + } + } + } + """ + + res = schema.execute_sync(query) + assert res.errors is None + assert res.data == { + "fruits": { + "totalCount": 4, + "results": [{"name": "Apple"}, {"name": "Banana"}], + } + } + + res = schema.execute_sync(query, variable_values={"pagination": {"offset": 1}}) + assert res.errors is None + assert res.data == { + "fruits": { + "totalCount": 4, + "results": [{"name": "Banana"}, {"name": "Strawberry"}], + } + } + + # Setting limit to None should return all results + res = schema.execute_sync(query, variable_values={"pagination": {"limit": None}}) + assert res.errors is None + assert res.data == { + "fruits": { + "totalCount": 4, + "results": [ + {"name": "Apple"}, + {"name": "Banana"}, + {"name": "Strawberry"}, + {"name": "Watermelon"}, + ], + } + } From 03a5783d07651706318e914a708e296a2b1d5e95 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 15 Dec 2024 10:21:10 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- strawberry_django/pagination.py | 2 +- tests/test_paginated_type.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/strawberry_django/pagination.py b/strawberry_django/pagination.py index 6ca9a699..6d4f7a56 100644 --- a/strawberry_django/pagination.py +++ b/strawberry_django/pagination.py @@ -13,9 +13,9 @@ from strawberry_django.fields.base import StrawberryDjangoFieldBase from strawberry_django.resolvers import django_resolver -from .settings import strawberry_django_settings from .arguments import argument +from .settings import strawberry_django_settings NodeType = TypeVar("NodeType") _QS = TypeVar("_QS", bound=QuerySet) diff --git a/tests/test_paginated_type.py b/tests/test_paginated_type.py index db692c06..2e369e3b 100644 --- a/tests/test_paginated_type.py +++ b/tests/test_paginated_type.py @@ -1,10 +1,10 @@ import textwrap from typing import Annotated -from django.test.utils import override_settings import pytest import strawberry from django.db.models import QuerySet +from django.test.utils import override_settings import strawberry_django from strawberry_django.optimizer import DjangoOptimizerExtension