Fix pagination behavior when page # exceeds search results (#4817)
# What this PR does Change pagination to return last available page if the page number exceeds the pages available instead of returning 404. This came up from if the user is on a page other than the first and they enter a search and the number of search results are smaller than what would be needed to reach the current page number it would give a blank page and 404. ## Which issue(s) this PR closes Related to [issue link here] <!-- *Note*: If you want the issue to be auto-closed once the PR is merged, change "Related to" to "Closes" in the line above. If you have more than one GitHub issue that this PR closes, be sure to preface each issue link with a [closing keyword](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests#linking-a-pull-request-to-an-issue). This ensures that the issue(s) are auto-closed once the PR has been merged. --> ## Checklist - [x] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes. --------- Co-authored-by: Rares Mardare <rares.mardare@grafana.com>
This commit is contained in:
parent
7112be8116
commit
f79445fbcb
3 changed files with 46 additions and 6 deletions
|
|
@ -447,10 +447,9 @@ def test_pagination(settings, alert_group_public_api_setup):
|
|||
token, alert_groups, _, _ = alert_group_public_api_setup
|
||||
client = APIClient()
|
||||
|
||||
url = reverse("api-public:alert_groups-list")
|
||||
url = "{}?perpage=1".format(reverse("api-public:alert_groups-list"))
|
||||
|
||||
with patch("common.api_helpers.paginators.PathPrefixedPagePagination.get_page_size", return_value=1):
|
||||
response = client.get(url, HTTP_AUTHORIZATION=token)
|
||||
response = client.get(url, HTTP_AUTHORIZATION=token)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
result = response.json()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import typing
|
||||
|
||||
from django.core.paginator import EmptyPage
|
||||
from rest_framework.pagination import BasePagination, CursorPagination, PageNumberPagination
|
||||
from rest_framework.response import Response
|
||||
|
||||
|
|
@ -54,6 +55,44 @@ class PathPrefixedPagePagination(BasePathPrefixedPagination, PageNumberPaginatio
|
|||
)
|
||||
return paginated_schema
|
||||
|
||||
def paginate_queryset(self, queryset, request, view=None):
|
||||
request.build_absolute_uri = lambda: create_engine_url(request.get_full_path())
|
||||
per_page = request.query_params.get(self.page_size_query_param, self.page_size)
|
||||
try:
|
||||
per_page = int(per_page)
|
||||
except ValueError:
|
||||
per_page = self.page_size
|
||||
|
||||
if per_page < 1:
|
||||
per_page = self.page_size
|
||||
|
||||
paginator = self.django_paginator_class(queryset, per_page)
|
||||
page_number = request.query_params.get(self.page_query_param, 1)
|
||||
try:
|
||||
page_number = int(page_number)
|
||||
except ValueError:
|
||||
page_number = 1
|
||||
|
||||
if page_number < 1:
|
||||
page_number = 1
|
||||
|
||||
try:
|
||||
self.page = self.get_page(page_number, paginator)
|
||||
except EmptyPage:
|
||||
self.page = paginator.page(paginator.num_pages)
|
||||
|
||||
if paginator.num_pages > 1 and self.template is not None:
|
||||
self.display_page_controls = True
|
||||
|
||||
self.request = request
|
||||
return list(self.page)
|
||||
|
||||
def get_page(self, page_number, paginator):
|
||||
try:
|
||||
return paginator.page(page_number)
|
||||
except EmptyPage:
|
||||
return paginator.page(paginator.num_pages)
|
||||
|
||||
|
||||
class PathPrefixedCursorPagination(BasePathPrefixedPagination, CursorPagination):
|
||||
def get_paginated_response(self, data: PaginatedData) -> Response:
|
||||
|
|
|
|||
|
|
@ -660,6 +660,7 @@ class _IntegrationsPage extends React.Component<IntegrationsProps, IntegrationsS
|
|||
|
||||
invalidateRequestFn = (requestedPage: number) => {
|
||||
const { store } = this.props;
|
||||
|
||||
return requestedPage !== store.filtersStore.currentTablePageNum[PAGE.Integrations];
|
||||
};
|
||||
|
||||
|
|
@ -696,6 +697,10 @@ class _IntegrationsPage extends React.Component<IntegrationsProps, IntegrationsS
|
|||
const { alertReceiveChannelStore } = store;
|
||||
const newPage = isOnMount ? store.filtersStore.currentTablePageNum[PAGE.Integrations] : 1;
|
||||
|
||||
runInAction(() => {
|
||||
store.filtersStore.currentTablePageNum[PAGE.Integrations] = newPage;
|
||||
});
|
||||
|
||||
await alertReceiveChannelStore.fetchPaginatedItems({
|
||||
filters: this.getFiltersBasedOnCurrentTab(),
|
||||
page: newPage,
|
||||
|
|
@ -703,9 +708,6 @@ class _IntegrationsPage extends React.Component<IntegrationsProps, IntegrationsS
|
|||
invalidateFn: () => this.invalidateRequestFn(newPage),
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
store.filtersStore.currentTablePageNum[PAGE.Integrations] = newPage;
|
||||
});
|
||||
LocationHelper.update({ p: newPage }, 'partial');
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue