Skip to content

Commit

Permalink
Better slicing of endpoint querysets
Browse files Browse the repository at this point in the history
  • Loading branch information
fsbraun committed Nov 11, 2024
1 parent ba4cae5 commit 8267ad0
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ smaller the average result set size. The default is 0::

By default django CMS Link will paginate the search results. You can change the
page size by setting the ``DJANGOCMS_LINK_PAGINATE_BY`` setting.
The default is 100::
The default is 50::

# Show 100 results per "page"
DJANGOCMS_LINK_PAGINATE_BY = 100
Expand Down
37 changes: 31 additions & 6 deletions djangocms_link/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
from django.contrib import admin
from django.core.exceptions import FieldError, PermissionDenied
from django.db.models import OuterRef, Q, Subquery
from django.http import JsonResponse
from django.http import Http404, JsonResponse
from django.urls import path
from django.utils.translation import gettext as _
from django.views.generic.list import BaseListView

from cms import __version__
Expand Down Expand Up @@ -33,7 +34,7 @@ class GrouperModelAdmin:
class AdminUrlsView(BaseListView):
"""Handle AutocompleteWidget's AJAX requests for data."""

paginate_by = getattr(settings, "DJANGOCMS_LINK_PAGINATE_BY", 100)
paginate_by = getattr(settings, "DJANGOCMS_LINK_PAGINATE_BY", 50)
admin_site = None

def get(self, request, *args, **kwargs):
Expand All @@ -54,8 +55,9 @@ def get(self, request, *args, **kwargs):
if not self.has_perm(request):
raise PermissionDenied

self.object_list = self.get_queryset()
self.add_admin_querysets(self.object_list)
qs_list = [self.get_queryset()]
self.add_admin_querysets(qs_list)
self.object_list = self.get_paginated_multi_qs(qs_list)
context = self.get_context_data()
results = self.get_optgroups(context)
return JsonResponse(
Expand All @@ -65,6 +67,28 @@ def get(self, request, *args, **kwargs):
}
)

def get_page(self):
page_kwarg = self.page_kwarg
page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1
try:
page_number = int(page)
except ValueError:
raise Http404(
_("Page is not “last”, nor can it be converted to an int.")
)
return page_number

def get_paginated_multi_qs(self, qs_list):
"""
Paginate multiple querysets and return a result list.
"""
if len(qs_list) == 1:
# Only one qs, just use regular pagination
return qs_list[0]
# Slize all querysets, evaluate and join them into a list
max_items = self.get_page() * self.paginate_by
return sum((list(qs[:max_items]) for qs in qs_list), start=[])

def get_reference(self, request):
try:
model_str, pk = request.GET.get("g").split(":")
Expand Down Expand Up @@ -113,6 +137,7 @@ def serialize_result(self, obj):
"id": f"{obj._meta.app_label}.{obj._meta.model_name}:{obj.pk}",
"text": getattr(obj, "__link_text__", str(obj)) or str(obj),
"url": obj.get_absolute_url(),
"verbose_name": str(obj._meta.verbose_name).capitalize(),
}

def get_queryset(self):
Expand Down Expand Up @@ -157,7 +182,7 @@ def get_queryset(self):
)
if self.site:
qs = qs.filter(node__site_id=self.site)
return list(qs)
return qs

def add_admin_querysets(self, qs):
for model_admin in REGISTERED_ADMIN:
Expand All @@ -183,7 +208,7 @@ def add_admin_querysets(self, qs):
if search_use_distinct: # pragma: no cover
new_qs = new_qs.distinct()

qs += list(new_qs)
qs.append(new_qs)
except Exception: # pragma: no cover
# Still report back remaining urls even if one model fails
pass
Expand Down
5 changes: 5 additions & 0 deletions tests/test_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ def tearDown(self):
self.subling.delete()

def test_api_endpoint(self):
from djangocms_link import admin

registered = admin.REGISTERED_ADMIN
admin.REGISTERED_ADMIN = []
for query_params in ("", "?app_label=1"):
with self.subTest(query_params=query_params):
with self.login_user_context(self.get_superuser()):
Expand All @@ -65,6 +69,7 @@ def test_api_endpoint(self):
_, pk = page["id"].split(":")
db_page = Page.objects.get(pk=pk)
self.assertEqual(page["text"], str(db_page))
admin.REGISTERED_ADMIN = registered

def test_filter(self):
with self.login_user_context(self.get_superuser()):
Expand Down

0 comments on commit 8267ad0

Please sign in to comment.