From 7f02d51ba04a533391a2c09b5f780fc8b0193ef7 Mon Sep 17 00:00:00 2001 From: Andrew Godwin Date: Mon, 12 Dec 2022 00:38:02 -0700 Subject: Add generic paginator for API --- api/pagination.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 api/pagination.py (limited to 'api/pagination.py') 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)]) -- cgit v1.2.3