-
Notifications
You must be signed in to change notification settings - Fork 3
Query for less data on pagination count #3106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -23,7 +23,6 @@ | |||||
| from rest_framework.decorators import action | ||||||
| from rest_framework.filters import OrderingFilter | ||||||
| from rest_framework.generics import get_object_or_404 | ||||||
| from rest_framework.pagination import LimitOffsetPagination | ||||||
| from rest_framework.permissions import IsAuthenticated | ||||||
| from rest_framework.response import Response | ||||||
| from rest_framework_nested.viewsets import NestedViewSetMixin | ||||||
|
|
@@ -104,6 +103,7 @@ | |||||
| ) | ||||||
| from main.constants import VALID_HTTP_METHODS | ||||||
| from main.filters import MultipleOptionsFilterBackend | ||||||
| from main.pagination import LargePagination | ||||||
| from main.permissions import ( | ||||||
| AnonymousAccessReadonlyPermission, | ||||||
| is_admin_user, | ||||||
|
|
@@ -130,22 +130,6 @@ def show_content_file_content(user): | |||||
| log = logging.getLogger(__name__) | ||||||
|
|
||||||
|
|
||||||
| class DefaultPagination(LimitOffsetPagination): | ||||||
| """ | ||||||
| Pagination class for learning_resources viewsets which gets default_limit and max_limit from settings | ||||||
| """ # noqa: E501 | ||||||
|
|
||||||
| default_limit = 10 | ||||||
| max_limit = 100 | ||||||
|
|
||||||
|
|
||||||
| class LargePagination(DefaultPagination): | ||||||
| """Large pagination for small resources, e.g., topics.""" | ||||||
|
|
||||||
| default_limit = 1000 | ||||||
| max_limit = 1000 | ||||||
|
|
||||||
|
|
||||||
| @extend_schema_view( | ||||||
| list=extend_schema( | ||||||
| summary="List", | ||||||
|
|
@@ -162,7 +146,6 @@ class BaseLearningResourceViewSet(viewsets.ReadOnlyModelViewSet): | |||||
| """ | ||||||
|
|
||||||
| permission_classes = (AnonymousAccessReadonlyPermission,) | ||||||
| pagination_class = DefaultPagination | ||||||
| filter_backends = [MultipleOptionsFilterBackend] | ||||||
| filterset_class = LearningResourceFilter | ||||||
| lookup_field = "id" | ||||||
|
|
@@ -334,7 +317,11 @@ def summary(self, request, **kwargs): # noqa: ARG002 | |||||
| Intended to be performant with large page sizes. | ||||||
| """ | ||||||
| queryset = self.filter_queryset( | ||||||
| self.get_queryset().values("id", "last_modified") | ||||||
| # we don't use `self.get_queryset()` here because there are incomplatible | ||||||
|
||||||
| # we don't use `self.get_queryset()` here because there are incomplatible | |
| # we don't use `self.get_queryset()` here because there are incompatible |
Copilot
AI
Mar 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The summary action now builds its own base queryset without .distinct(). Because LearningResource filters include many-to-many relations (e.g., topics/departments), filtering can introduce duplicate rows unless the queryset is made distinct. Consider applying .distinct() after filter_queryset (or otherwise ensuring uniqueness) to preserve correct counts/results.
| ) | |
| ).distinct() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| from rest_framework.pagination import LimitOffsetPagination | ||
|
|
||
|
|
||
| class DefaultPagination(LimitOffsetPagination): | ||
| """ | ||
| Default pagination class for rest APIs | ||
| """ | ||
|
|
||
| count_fields = ("pk",) | ||
|
|
||
| default_limit = 10 | ||
| max_limit = 100 | ||
|
|
||
| def get_count(self, queryset): | ||
| """Get the count of objects in the queryset""" | ||
| # we additionally filter this down to a subset of fields | ||
| return queryset.only(*self.count_fields).count() | ||
|
|
||
|
|
||
| class LargePagination(DefaultPagination): | ||
| """Large pagination for small resources, e.g., topics.""" | ||
|
|
||
| default_limit = 1000 | ||
| max_limit = 1000 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -664,6 +664,7 @@ def get_all_config_keys(): | |
| "DEFAULT_AUTHENTICATION_CLASSES": ( | ||
| "rest_framework.authentication.SessionAuthentication", | ||
| ), | ||
| "DEFAULT_PAGINATION_CLASS": "main.pagination.DefaultPagination", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we're now setting DEFAULT_PAGINATION_CLASS in settings, some endpoints might switch from returning a plain list ([]) to a full paginated response ({count, next, previous, results}).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (doesn't hurt to check, but this is the sort of thing our OpenAPI CI check should actualy be very good at catching) |
||
| "EXCEPTION_HANDLER": "main.exceptions.api_exception_handler", | ||
| "TEST_REQUEST_DEFAULT_FORMAT": "json", | ||
| "TEST_REQUEST_RENDERER_CLASSES": [ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing DefaultPagination/LargePagination from learning_resources.views breaks existing imports (e.g., testimonials/views.py imports LargePagination from learning_resources.views). Update those imports/usages to point to main.pagination (or re-export from learning_resources.views) to avoid ImportError at runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to make this change at
mit-learn/testimonials/views.py
Line 7 in 088cac9