Skip to content

Commit

Permalink
Merge pull request #5 from openradx/related-pagination-mixin
Browse files Browse the repository at this point in the history
Related pagination mixin
  • Loading branch information
medihack committed Jul 23, 2024
2 parents 5c706a2 + 4309883 commit 1e06f95
Showing 1 changed file with 59 additions and 12 deletions.
71 changes: 59 additions & 12 deletions adit_radis_shared/common/mixins.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Any, Protocol

from django.core.exceptions import SuspiciousOperation
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from django.db.models import QuerySet
from django.http import HttpRequest, HttpResponse
from django.views.generic import TemplateView
Expand All @@ -16,14 +17,11 @@
class ViewProtocol(Protocol):
request: HttpRequest

def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
...
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...

def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
...
def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: ...

def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
...
def get_context_data(self, **kwargs: Any) -> dict[str, Any]: ...


class LockedMixinProtocol(ViewProtocol, Protocol):
Expand Down Expand Up @@ -63,14 +61,11 @@ class RelatedFilterMixinProtocol(ViewProtocol, Protocol):
filterset: FilterSet
object_list: QuerySet

def get_strict(self) -> bool:
...
def get_strict(self) -> bool: ...

def get_filterset_class(self) -> type[FilterSet]:
...
def get_filterset_class(self) -> type[FilterSet]: ...

def get_filterset(self, filterset_class: type[FilterSet]) -> FilterSet:
...
def get_filterset(self, filterset_class: type[FilterSet]) -> FilterSet: ...


class RelatedFilterMixin(FilterMixin):
Expand Down Expand Up @@ -147,3 +142,55 @@ def get_context_data(self: PageSizeSelectMixinProtocol, **kwargs):
context["page_size_select"] = PageSizeSelectForm(self.request.GET, self.page_sizes)

return context


class RelatedPaginationMixinProtocol(ViewProtocol, Protocol):
object_list: QuerySet
paginate_by: int

def get_object(self) -> Any: ...

def get_context_data(self, **kwargs) -> dict[str, Any]: ...

def get_related_queryset(self) -> QuerySet: ...


class RelatedPaginationMixin:
"""This mixin provides pagination for a related queryset. This makes it possible to
paginate a related queryset in a DetailView. The related queryset is obtained by
the `get_related_queryset()` method that must be implemented by the subclass.
If used in combination with `RelatedFilterMixin`, the `RelatedPaginationMixin` must be
inherited first."""

request: HttpRequest

def get_related_queryset(self: RelatedPaginationMixinProtocol) -> QuerySet:
raise NotImplementedError("You must implement this method")

def get_context_data(self: RelatedPaginationMixinProtocol, **kwargs):
context = super().get_context_data(**kwargs)

if "object_list" in context:
queryset = context["object_list"]
else:
queryset = self.get_related_queryset()

paginator = Paginator(queryset, self.paginate_by)
page = self.request.GET.get("page")

if page is None:
page = 1

try:
paginated_queryset = paginator.page(page)
except PageNotAnInteger:
paginated_queryset = paginator.page(1)
except EmptyPage:
paginated_queryset = paginator.page(paginator.num_pages)

context["object_list"] = paginated_queryset
context["paginator"] = paginator
context["is_paginated"] = paginated_queryset.has_other_pages()
context["page_obj"] = paginated_queryset

return context

0 comments on commit 1e06f95

Please sign in to comment.