summaryrefslogtreecommitdiffstats
path: root/api/pagination.py
diff options
context:
space:
mode:
Diffstat (limited to 'api/pagination.py')
-rw-r--r--api/pagination.py45
1 files changed, 45 insertions, 0 deletions
diff --git a/api/pagination.py b/api/pagination.py
new file mode 100644
index 0000000..0539ae8
--- /dev/null
+++ b/api/pagination.py
@@ -0,0 +1,45 @@
+class MastodonPaginator:
+ """
+ Paginates in the Mastodon style (max_id, min_id, etc)
+ """
+
+ def __init__(
+ self,
+ anchor_model,
+ sort_attribute: str = "created",
+ default_limit: int = 20,
+ max_limit: int = 40,
+ ):
+ self.anchor_model = anchor_model
+ self.sort_attribute = sort_attribute
+ self.default_limit = default_limit
+ self.max_limit = max_limit
+
+ def paginate(
+ self,
+ queryset,
+ min_id: str | None,
+ max_id: str | None,
+ since_id: str | None,
+ limit: int | None,
+ ):
+ if max_id:
+ anchor = self.anchor_model.objects.get(pk=max_id)
+ queryset = queryset.filter(
+ **{self.sort_attribute + "__lt": getattr(anchor, self.sort_attribute)}
+ )
+ if since_id:
+ anchor = self.anchor_model.objects.get(pk=since_id)
+ queryset = queryset.filter(
+ **{self.sort_attribute + "__gt": getattr(anchor, self.sort_attribute)}
+ )
+ if min_id:
+ # Min ID requires items _immediately_ newer than specified, so we
+ # invert the ordering to accomodate
+ anchor = self.anchor_model.objects.get(pk=min_id)
+ queryset = queryset.filter(
+ **{self.sort_attribute + "__gt": getattr(anchor, self.sort_attribute)}
+ ).order_by(self.sort_attribute)
+ else:
+ queryset = queryset.order_by("-" + self.sort_attribute)
+ return list(queryset[: min(limit or self.default_limit, self.max_limit)])