diff options
author | Andrew Godwin | 2022-12-12 00:38:02 -0700 |
---|---|---|
committer | Andrew Godwin | 2022-12-12 11:56:49 -0700 |
commit | 7f02d51ba04a533391a2c09b5f780fc8b0193ef7 (patch) | |
tree | fe066085872b7aa721b270ebe588b4265cdc8b73 /api/pagination.py | |
parent | f892c0c4ceefcaacb3c586de96e8f4a8430ee840 (diff) | |
download | takahe-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.py | 45 |
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)]) |