diff --git a/docs/docs/guides/response/pagination.md b/docs/docs/guides/response/pagination.md index f9c771a23..3458345da 100644 --- a/docs/docs/guides/response/pagination.md +++ b/docs/docs/guides/response/pagination.md @@ -118,6 +118,7 @@ To create a custom pagination class you should subclass `ninja.pagination.Pagina Example: ```python hl_lines="7 11 16 26" +from django.http import HttpRequest from ninja.pagination import paginate, PaginationBase from ninja import Schema @@ -133,7 +134,7 @@ class CustomPagination(PaginationBase): total: int per_page: int - def paginate_queryset(self, queryset, pagination: Input, **params): + def paginate_queryset(self, queryset, *, pagination: Input, request: HttpRequest, **params): skip = pagination.skip return { 'items': queryset[skip : skip + 5], @@ -148,13 +149,6 @@ def list_users(request): return User.objects.all() ``` -Tip: You can access request object from params: - -```python -def paginate_queryset(self, queryset, pagination: Input, **params): - request = params["request"] -``` - #### Async Pagination Standard **Django Ninja** pagination classes support async. If you wish to handle async requests with a custom pagination class, you should subclass `ninja.pagination.AsyncPaginationBase` and override the `apaginate_queryset(self, queryset, request, **params)` method. diff --git a/ninja/pagination.py b/ninja/pagination.py index 7a5f76f82..a307222c5 100644 --- a/ninja/pagination.py +++ b/ninja/pagination.py @@ -41,7 +41,9 @@ def __init__(self, *, pass_parameter: Optional[str] = None, **kwargs: Any) -> No def paginate_queryset( self, queryset: QuerySet, + *, pagination: Any, + request: HttpRequest, **params: Any, ) -> Any: pass # pragma: no cover @@ -63,7 +65,9 @@ class AsyncPaginationBase(PaginationBase): async def apaginate_queryset( self, queryset: QuerySet, + *, pagination: Any, + request: HttpRequest, **params: Any, ) -> Any: pass # pragma: no cover @@ -91,7 +95,9 @@ class Input(Schema): def paginate_queryset( self, queryset: QuerySet, + *, pagination: Input, + request: HttpRequest, **params: Any, ) -> Any: offset = pagination.offset @@ -104,7 +110,9 @@ def paginate_queryset( async def apaginate_queryset( self, queryset: QuerySet, + *, pagination: Input, + request: HttpRequest, **params: Any, ) -> Any: offset = pagination.offset @@ -143,7 +151,9 @@ def _get_page_size(self, requested_page_size: Optional[int]) -> int: def paginate_queryset( self, queryset: QuerySet, + *, pagination: Input, + request: HttpRequest, **params: Any, ) -> Any: page_size = self._get_page_size(pagination.page_size) @@ -156,7 +166,9 @@ def paginate_queryset( async def apaginate_queryset( self, queryset: QuerySet, + *, pagination: Input, + request: HttpRequest, **params: Any, ) -> Any: page_size = self._get_page_size(pagination.page_size) diff --git a/tests/test_openapi_schema.py b/tests/test_openapi_schema.py index fe5d08478..276498c03 100644 --- a/tests/test_openapi_schema.py +++ b/tests/test_openapi_schema.py @@ -926,7 +926,7 @@ class Output(Schema): items_attribute: str = "data" - def paginate_queryset(self, queryset, pagination, **params): + def paginate_queryset(self, queryset, *, pagination, request, **params): pass @api.get( diff --git a/tests/test_pagination.py b/tests/test_pagination.py index 94b599738..e4690a5ee 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py @@ -3,6 +3,7 @@ from typing import Any, List import pytest +from django.http import HttpRequest from django.test import override_settings from pydantic.errors import PydanticSchemaGenerationError @@ -34,6 +35,7 @@ class Output(Schema): count: str skip: int + # Explicitly exclude "request", as the previous signature didn't guarantee it def paginate_queryset(self, items, pagination: Input, **params): skip = pagination.skip return { @@ -50,7 +52,7 @@ class Input(Schema): Output = None - def paginate_queryset(self, items, pagination: Input, **params): + def paginate_queryset(self, items, *, pagination: Input, request: HttpRequest, **params): skip = pagination.skip return items[skip : skip + 5] @@ -68,7 +70,7 @@ class Output(Schema): items_attribute: str = "results" - def paginate_queryset(self, items, pagination: Input, **params): + def paginate_queryset(self, items, *, pagination: Input, request: HttpRequest, **params): skip = pagination.skip return { "results": items[skip : skip + 5], @@ -87,7 +89,7 @@ class Output(Schema): next: str = None prev: str = None - def paginate_queryset(self, items, pagination: Input, request, **params): + def paginate_queryset(self, items, *, pagination: Input, request: HttpRequest, **params): skip = pagination.skip prev_skip = skip - 5 if prev_skip < 0: diff --git a/tests/test_pagination_async.py b/tests/test_pagination_async.py index afe1720c0..4595af1f1 100644 --- a/tests/test_pagination_async.py +++ b/tests/test_pagination_async.py @@ -3,6 +3,7 @@ import django import pytest +from django.http import HttpRequest from django.db.models import QuerySet from someapp.models import Category @@ -31,7 +32,7 @@ class Output(Schema): count: str skip: int - def paginate_queryset(self, items, pagination: Input, **params): + def paginate_queryset(self, items, *, pagination: Input, request: HttpRequest, **params): skip = pagination.skip return { "items": items[skip : skip + 5], @@ -47,7 +48,7 @@ class Input(Schema): Output = None - def paginate_queryset(self, items, pagination: Input, **params): + def paginate_queryset(self, items, *, pagination: Input, request: HttpRequest, **params): skip = pagination.skip return items[skip : skip + 5]