authentik.api.pagination

Pagination which includes total pages and current page

 1"""Pagination which includes total pages and current page"""
 2
 3from typing import TYPE_CHECKING
 4
 5from drf_spectacular.plumbing import build_object_type
 6from rest_framework import pagination
 7from rest_framework.response import Response
 8
 9from authentik.api.search.ql import QLSearch
10from authentik.api.v3.schema.pagination import PAGINATION
11from authentik.api.v3.schema.search import AUTOCOMPLETE_SCHEMA
12
13if TYPE_CHECKING:
14    from django.db.models import QuerySet
15    from rest_framework.request import Request
16
17
18class Pagination(pagination.PageNumberPagination):
19    """Pagination which includes total pages and current page"""
20
21    page_query_param = "page"
22    page_size_query_param = "page_size"
23
24    def get_page_size(self, request: Request) -> int:
25        if self.page_size_query_param in request.query_params:
26            page_size = super().get_page_size(request)
27            if page_size is not None:
28                return min(super().get_page_size(request), request.tenant.pagination_max_page_size)
29        return request.tenant.pagination_default_page_size
30
31    def get_paginated_response(self, data) -> Response:
32        previous_page_number = 0
33        if self.page.has_previous():
34            previous_page_number = self.page.previous_page_number()
35        next_page_number = 0
36        if self.page.has_next():
37            next_page_number = self.page.next_page_number()
38        return Response(
39            {
40                "pagination": {
41                    "next": next_page_number,
42                    "previous": previous_page_number,
43                    "count": self.page.paginator.count,
44                    "current": self.page.number,
45                    "total_pages": self.page.paginator.num_pages,
46                    "start_index": self.page.start_index(),
47                    "end_index": self.page.end_index(),
48                },
49                "results": data,
50                "autocomplete": self.get_autocomplete(),
51            }
52        )
53
54    def paginate_queryset(self, queryset: QuerySet, request: Request, view=None):
55        self.view = view
56        return super().paginate_queryset(queryset, request, view)
57
58    def get_autocomplete(self):
59        schema = QLSearch().get_schema(self.request, self.view)
60        introspections = {}
61        if hasattr(self.view, "get_ql_fields"):
62            from authentik.api.search.schema import AKQLSchemaSerializer
63
64            introspections = AKQLSchemaSerializer().serialize(
65                schema(self.page.paginator.object_list.model)
66            )
67        return introspections
68
69    def get_paginated_response_schema(self, schema):
70        return build_object_type(
71            properties={
72                "pagination": PAGINATION.ref,
73                "results": schema,
74                "autocomplete": AUTOCOMPLETE_SCHEMA.ref,
75            },
76            required=["pagination", "results", "autocomplete"],
77        )
78
79
80class SmallerPagination(Pagination):
81    """Smaller pagination for objects which might require a lot of queries
82    to retrieve all data for."""
83
84    max_page_size = 10
class Pagination(rest_framework.pagination.PageNumberPagination):
19class Pagination(pagination.PageNumberPagination):
20    """Pagination which includes total pages and current page"""
21
22    page_query_param = "page"
23    page_size_query_param = "page_size"
24
25    def get_page_size(self, request: Request) -> int:
26        if self.page_size_query_param in request.query_params:
27            page_size = super().get_page_size(request)
28            if page_size is not None:
29                return min(super().get_page_size(request), request.tenant.pagination_max_page_size)
30        return request.tenant.pagination_default_page_size
31
32    def get_paginated_response(self, data) -> Response:
33        previous_page_number = 0
34        if self.page.has_previous():
35            previous_page_number = self.page.previous_page_number()
36        next_page_number = 0
37        if self.page.has_next():
38            next_page_number = self.page.next_page_number()
39        return Response(
40            {
41                "pagination": {
42                    "next": next_page_number,
43                    "previous": previous_page_number,
44                    "count": self.page.paginator.count,
45                    "current": self.page.number,
46                    "total_pages": self.page.paginator.num_pages,
47                    "start_index": self.page.start_index(),
48                    "end_index": self.page.end_index(),
49                },
50                "results": data,
51                "autocomplete": self.get_autocomplete(),
52            }
53        )
54
55    def paginate_queryset(self, queryset: QuerySet, request: Request, view=None):
56        self.view = view
57        return super().paginate_queryset(queryset, request, view)
58
59    def get_autocomplete(self):
60        schema = QLSearch().get_schema(self.request, self.view)
61        introspections = {}
62        if hasattr(self.view, "get_ql_fields"):
63            from authentik.api.search.schema import AKQLSchemaSerializer
64
65            introspections = AKQLSchemaSerializer().serialize(
66                schema(self.page.paginator.object_list.model)
67            )
68        return introspections
69
70    def get_paginated_response_schema(self, schema):
71        return build_object_type(
72            properties={
73                "pagination": PAGINATION.ref,
74                "results": schema,
75                "autocomplete": AUTOCOMPLETE_SCHEMA.ref,
76            },
77            required=["pagination", "results", "autocomplete"],
78        )

Pagination which includes total pages and current page

page_query_param = 'page'
page_size_query_param = 'page_size'
def get_page_size(unknown):
25    def get_page_size(self, request: Request) -> int:
26        if self.page_size_query_param in request.query_params:
27            page_size = super().get_page_size(request)
28            if page_size is not None:
29                return min(super().get_page_size(request), request.tenant.pagination_max_page_size)
30        return request.tenant.pagination_default_page_size
def get_paginated_response(self, data) -> rest_framework.response.Response:
32    def get_paginated_response(self, data) -> Response:
33        previous_page_number = 0
34        if self.page.has_previous():
35            previous_page_number = self.page.previous_page_number()
36        next_page_number = 0
37        if self.page.has_next():
38            next_page_number = self.page.next_page_number()
39        return Response(
40            {
41                "pagination": {
42                    "next": next_page_number,
43                    "previous": previous_page_number,
44                    "count": self.page.paginator.count,
45                    "current": self.page.number,
46                    "total_pages": self.page.paginator.num_pages,
47                    "start_index": self.page.start_index(),
48                    "end_index": self.page.end_index(),
49                },
50                "results": data,
51                "autocomplete": self.get_autocomplete(),
52            }
53        )
def paginate_queryset(unknown):
55    def paginate_queryset(self, queryset: QuerySet, request: Request, view=None):
56        self.view = view
57        return super().paginate_queryset(queryset, request, view)

Paginate a queryset if required, either returning a page object, or None if pagination is not configured for this view.

def get_autocomplete(self):
59    def get_autocomplete(self):
60        schema = QLSearch().get_schema(self.request, self.view)
61        introspections = {}
62        if hasattr(self.view, "get_ql_fields"):
63            from authentik.api.search.schema import AKQLSchemaSerializer
64
65            introspections = AKQLSchemaSerializer().serialize(
66                schema(self.page.paginator.object_list.model)
67            )
68        return introspections
def get_paginated_response_schema(self, schema):
70    def get_paginated_response_schema(self, schema):
71        return build_object_type(
72            properties={
73                "pagination": PAGINATION.ref,
74                "results": schema,
75                "autocomplete": AUTOCOMPLETE_SCHEMA.ref,
76            },
77            required=["pagination", "results", "autocomplete"],
78        )
class SmallerPagination(Pagination):
81class SmallerPagination(Pagination):
82    """Smaller pagination for objects which might require a lot of queries
83    to retrieve all data for."""
84
85    max_page_size = 10

Smaller pagination for objects which might require a lot of queries to retrieve all data for.

max_page_size = 10