Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions docs/docs/guides/response/pagination.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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],
Expand All @@ -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.
Expand Down
12 changes: 12 additions & 0 deletions ninja/pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -91,7 +95,9 @@ class Input(Schema):
def paginate_queryset(
self,
queryset: QuerySet,
*,
pagination: Input,
request: HttpRequest,
**params: Any,
) -> Any:
offset = pagination.offset
Expand All @@ -104,7 +110,9 @@ def paginate_queryset(
async def apaginate_queryset(
self,
queryset: QuerySet,
*,
pagination: Input,
request: HttpRequest,
**params: Any,
) -> Any:
offset = pagination.offset
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_openapi_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
8 changes: 5 additions & 3 deletions tests/test_pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 {
Expand All @@ -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]

Expand All @@ -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],
Expand All @@ -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:
Expand Down
5 changes: 3 additions & 2 deletions tests/test_pagination_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import django
import pytest
from django.http import HttpRequest
from django.db.models import QuerySet
from someapp.models import Category

Expand Down Expand Up @@ -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],
Expand All @@ -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]

Expand Down