summaryrefslogtreecommitdiffstats
path: root/api/pagination.py
diff options
context:
space:
mode:
authorAndrew Godwin2022-12-12 00:38:02 -0700
committerAndrew Godwin2022-12-12 11:56:49 -0700
commit7f02d51ba04a533391a2c09b5f780fc8b0193ef7 (patch)
treefe066085872b7aa721b270ebe588b4265cdc8b73 /api/pagination.py
parentf892c0c4ceefcaacb3c586de96e8f4a8430ee840 (diff)
downloadtakahe-7f02d51ba04a533391a2c09b5f780fc8b0193ef7.tar.gz
takahe-7f02d51ba04a533391a2c09b5f780fc8b0193ef7.tar.bz2
takahe-7f02d51ba04a533391a2c09b5f780fc8b0193ef7.zip
Add generic paginator for API
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)])