1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Merge pull request #9527 from kkthxbye-code/fix-9374

Partially fixes #9374 - Implement a custom paginator for DeviceViewSet to improve config_context load times
This commit is contained in:
Jeremy Stretch
2022-06-17 13:44:37 -04:00
committed by GitHub
2 changed files with 19 additions and 1 deletions

View File

@ -19,6 +19,7 @@ from ipam.models import Prefix, VLAN
from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired
from netbox.api.exceptions import ServiceUnavailable
from netbox.api.metadata import ContentTypeMetadata
from netbox.api.pagination import StripCountAnnotationsPaginator
from netbox.api.viewsets import NetBoxModelViewSet
from netbox.config import get_config
from utilities.api import get_serializer_for_model
@ -392,6 +393,7 @@ class DeviceViewSet(ConfigContextQuerySetMixin, NetBoxModelViewSet):
'virtual_chassis__master', 'primary_ip4__nat_outside', 'primary_ip6__nat_outside', 'tags',
)
filterset_class = filtersets.DeviceFilterSet
pagination_class = StripCountAnnotationsPaginator
def get_serializer_class(self):
"""

View File

@ -16,7 +16,7 @@ class OptionalLimitOffsetPagination(LimitOffsetPagination):
def paginate_queryset(self, queryset, request, view=None):
if isinstance(queryset, QuerySet):
self.count = queryset.count()
self.count = self.get_queryset_count(queryset)
else:
# We're dealing with an iterable, not a QuerySet
self.count = len(queryset)
@ -52,6 +52,9 @@ class OptionalLimitOffsetPagination(LimitOffsetPagination):
return self.default_limit
def get_queryset_count(self, queryset):
return queryset.count()
def get_next_link(self):
# Pagination has been disabled
@ -67,3 +70,16 @@ class OptionalLimitOffsetPagination(LimitOffsetPagination):
return None
return super().get_previous_link()
class StripCountAnnotationsPaginator(OptionalLimitOffsetPagination):
"""
Strips the annotations on the queryset before getting the count
to optimize pagination of complex queries.
"""
def get_queryset_count(self, queryset):
# Clone the queryset to avoid messing up the actual query
cloned_queryset = queryset.all()
cloned_queryset.query.annotations.clear()
return cloned_queryset.count()