mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-25 00:36:11 -06:00
Remove TwoModePagination; override paginator() on NetBoxModelViewSet to determine paginator class
This commit is contained in:
parent
fd1c8aa44a
commit
a254398cec
@ -1,11 +1,13 @@
|
||||
from django.db.models import QuerySet
|
||||
from django.utils.encoding import force_str
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework.pagination import LimitOffsetPagination, CursorPagination, BasePagination, _reverse_ordering
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.pagination import LimitOffsetPagination, CursorPagination, _reverse_ordering
|
||||
|
||||
from netbox.config import get_config
|
||||
from rest_framework.compat import coreapi, coreschema
|
||||
|
||||
__all__ = (
|
||||
'CursorPaginationWithNoLimit',
|
||||
'OptionalLimitOffsetPagination',
|
||||
'PAGINATORS',
|
||||
)
|
||||
|
||||
|
||||
class OptionalLimitOffsetPagination(LimitOffsetPagination):
|
||||
@ -183,58 +185,7 @@ class CursorPaginationWithNoLimit(CursorPagination):
|
||||
return self.default_page_size
|
||||
|
||||
|
||||
class TwoModePagination(BasePagination):
|
||||
"""
|
||||
Pagination that allows user to toggle between LimitOffsetPagination and CursorPagination. The default
|
||||
is LimitOffsetPagination.
|
||||
"""
|
||||
pagination_mode_param = 'pagination_mode'
|
||||
pagination_mode_description = _(
|
||||
'Mode selector for LimitOffsetPagination (default) and CursorPagination.\n'
|
||||
'`offset` and `limit` are used for LimitOffsetPagination.\n'
|
||||
'`cursor` and `limit` are used for CursorPagination.')
|
||||
limit_offset_key = 'limit_offset'
|
||||
cursor_pagination_key = 'cursor'
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
limit_offset_paginator=OptionalLimitOffsetPagination,
|
||||
cursor_paginator=CursorPaginationWithNoLimit,
|
||||
) -> None:
|
||||
self._limit_offset_pagination = limit_offset_paginator()
|
||||
self._cursor_pagination = cursor_paginator()
|
||||
|
||||
self._chosen_pagination = self._limit_offset_pagination
|
||||
|
||||
def paginate_queryset(self, queryset, request: Response, view=None):
|
||||
mode = request.query_params.get(self.pagination_mode_param)
|
||||
if mode == self.cursor_pagination_key:
|
||||
self._chosen_pagination = self._cursor_pagination
|
||||
return self._chosen_pagination.paginate_queryset(queryset, request, view)
|
||||
|
||||
def get_paginated_response(self, data):
|
||||
return self._chosen_pagination.get_paginated_response(data)
|
||||
|
||||
def get_paginated_response_schema(self, schema):
|
||||
return self._chosen_pagination.get_paginated_response_schema(schema)
|
||||
|
||||
def to_html(self): # pragma: no cover
|
||||
return self._chosen_pagination.to_html()
|
||||
|
||||
def get_schema_fields(self, view):
|
||||
mode_field = coreapi.Field(
|
||||
name=self.pagination_mode_param,
|
||||
required=False,
|
||||
location='query',
|
||||
schema=coreschema.Enum(
|
||||
title='Pagination Mode',
|
||||
description=force_str(self.pagination_mode_description),
|
||||
enum=[self.limit_offset_key, self.cursor_pagination_key],
|
||||
)
|
||||
)
|
||||
return [mode_field] \
|
||||
+ self._limit_offset_pagination.get_schema_fields(view) \
|
||||
+ self._cursor_pagination.get_schema_fields(view)[:1] # "limit" is shared between the two modes
|
||||
|
||||
def get_schema_operation_parameters(self, view):
|
||||
return self._chosen_pagination.get_schema_operation_parameters(view)
|
||||
PAGINATORS = {
|
||||
'limit_offset': OptionalLimitOffsetPagination, # Default per settings.DEFAULT_PAGINATION_CLASS
|
||||
'cursor': CursorPaginationWithNoLimit,
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from extras.models import ExportTemplate
|
||||
from netbox.api.exceptions import SerializerNotFound
|
||||
from netbox.api.pagination import PAGINATORS
|
||||
from netbox.constants import NESTED_SERIALIZER_PREFIX
|
||||
from utilities.api import get_serializer_for_model
|
||||
from utilities.exceptions import AbortRequest
|
||||
@ -93,6 +94,20 @@ class NetBoxModelViewSet(BulkUpdateModelMixin, BulkDestroyModelMixin, ObjectVali
|
||||
|
||||
return super().get_queryset()
|
||||
|
||||
@property
|
||||
def paginator(self):
|
||||
"""
|
||||
Allow the request to designate the paginator class per the pagination_mode parameter.
|
||||
"""
|
||||
if not hasattr(self, '_paginator'):
|
||||
if self.pagination_class is None:
|
||||
self._paginator = None
|
||||
elif mode := self.request.query_params.get('pagination_mode'):
|
||||
self._paginator = PAGINATORS.get(mode, self.pagination_class)()
|
||||
else:
|
||||
self._paginator = self.pagination_class()
|
||||
return self._paginator
|
||||
|
||||
def initialize_request(self, request, *args, **kwargs):
|
||||
# Check if brief=True has been passed
|
||||
if request.method == 'GET' and request.GET.get('brief'):
|
||||
|
@ -530,7 +530,7 @@ REST_FRAMEWORK = {
|
||||
'rest_framework.filters.OrderingFilter',
|
||||
),
|
||||
'DEFAULT_METADATA_CLASS': 'netbox.api.metadata.BulkOperationMetadata',
|
||||
'DEFAULT_PAGINATION_CLASS': 'netbox.api.pagination.TwoModePagination',
|
||||
'DEFAULT_PAGINATION_CLASS': 'netbox.api.pagination.OptionalLimitOffsetPagination',
|
||||
'DEFAULT_PARSER_CLASSES': (
|
||||
'rest_framework.parsers.JSONParser',
|
||||
'rest_framework.parsers.MultiPartParser',
|
||||
|
Loading…
Reference in New Issue
Block a user