Refactor link header and fix empty page case
This commit is contained in:
parent
ea6f272047
commit
9c3806a175
|
@ -7,11 +7,19 @@ from django.http import HttpRequest
|
|||
|
||||
@dataclasses.dataclass
|
||||
class PaginationResult:
|
||||
"""
|
||||
Represents a pagination result for Mastodon (it does Link header stuff)
|
||||
"""
|
||||
|
||||
#: A list of objects that matched the pagination query.
|
||||
results: list[models.Model]
|
||||
|
||||
#: The actual applied limit, which may be different from what was requested.
|
||||
limit: int
|
||||
sort_attribute: str
|
||||
|
||||
@classmethod
|
||||
def empty(cls):
|
||||
return cls(results=[], limit=20)
|
||||
|
||||
def next(self, request: HttpRequest, allowed_params: list[str]):
|
||||
"""
|
||||
|
@ -37,6 +45,17 @@ class PaginationResult:
|
|||
|
||||
return f"{request.build_absolute_uri(request.path)}?{urllib.parse.urlencode(params)}"
|
||||
|
||||
def link_header(self, request: HttpRequest, allowed_params: list[str]):
|
||||
"""
|
||||
Creates a link header for the given request
|
||||
"""
|
||||
return ", ".join(
|
||||
(
|
||||
f'<{self.next(request, allowed_params)}>; rel="next"',
|
||||
f'<{self.prev(request, allowed_params)}>; rel="prev"',
|
||||
)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def filter_params(request: HttpRequest, allowed_params: list[str]):
|
||||
params = {}
|
||||
|
@ -71,12 +90,12 @@ class MastodonPaginator:
|
|||
max_id: str | None,
|
||||
since_id: str | None,
|
||||
limit: int | None,
|
||||
):
|
||||
) -> PaginationResult:
|
||||
if max_id:
|
||||
try:
|
||||
anchor = self.anchor_model.objects.get(pk=max_id)
|
||||
except self.anchor_model.DoesNotExist:
|
||||
return []
|
||||
return PaginationResult.empty()
|
||||
queryset = queryset.filter(
|
||||
**{self.sort_attribute + "__lt": getattr(anchor, self.sort_attribute)}
|
||||
)
|
||||
|
@ -85,7 +104,7 @@ class MastodonPaginator:
|
|||
try:
|
||||
anchor = self.anchor_model.objects.get(pk=since_id)
|
||||
except self.anchor_model.DoesNotExist:
|
||||
return []
|
||||
return PaginationResult.empty()
|
||||
queryset = queryset.filter(
|
||||
**{self.sort_attribute + "__gt": getattr(anchor, self.sort_attribute)}
|
||||
)
|
||||
|
@ -96,7 +115,7 @@ class MastodonPaginator:
|
|||
try:
|
||||
anchor = self.anchor_model.objects.get(pk=min_id)
|
||||
except self.anchor_model.DoesNotExist:
|
||||
return []
|
||||
return PaginationResult.empty()
|
||||
queryset = queryset.filter(
|
||||
**{self.sort_attribute + "__gt": getattr(anchor, self.sort_attribute)}
|
||||
).order_by(self.sort_attribute)
|
||||
|
@ -107,5 +126,4 @@ class MastodonPaginator:
|
|||
return PaginationResult(
|
||||
results=list(queryset[:limit]),
|
||||
limit=limit,
|
||||
sort_attribute=self.sort_attribute,
|
||||
)
|
||||
|
|
|
@ -132,20 +132,17 @@ def account_statuses(
|
|||
)
|
||||
|
||||
if pager.results:
|
||||
params = [
|
||||
"limit",
|
||||
"id",
|
||||
"exclude_reblogs",
|
||||
"exclude_replies",
|
||||
"only_media",
|
||||
"pinned",
|
||||
"tagged",
|
||||
]
|
||||
response.headers["Link"] = ", ".join(
|
||||
(
|
||||
f'<{pager.next(request, params)}>; rel="next"',
|
||||
f'<{pager.prev(request, params)}>; rel="prev"',
|
||||
)
|
||||
response.headers["Link"] = pager.link_header(
|
||||
request,
|
||||
[
|
||||
"limit",
|
||||
"id",
|
||||
"exclude_reblogs",
|
||||
"exclude_replies",
|
||||
"only_media",
|
||||
"pinned",
|
||||
"tagged",
|
||||
],
|
||||
)
|
||||
|
||||
interactions = PostInteraction.get_post_interactions(
|
||||
|
|
|
@ -45,13 +45,7 @@ def notifications(
|
|||
)
|
||||
|
||||
if pager.results:
|
||||
params = ["limit", "account_id"]
|
||||
response.headers["Link"] = ", ".join(
|
||||
(
|
||||
f'<{pager.next(request, params)}>; rel="next"',
|
||||
f'<{pager.prev(request, params)}>; rel="prev"',
|
||||
)
|
||||
)
|
||||
response.headers["Link"] = pager.link_header(request, ["limit", "account_id"])
|
||||
|
||||
interactions = PostInteraction.get_event_interactions(
|
||||
pager.results, request.identity
|
||||
|
|
|
@ -33,12 +33,7 @@ def home(
|
|||
)
|
||||
|
||||
if pager.results:
|
||||
response.headers["Link"] = ", ".join(
|
||||
(
|
||||
f"<{pager.next(request, ['limit'])}>; rel=\"next\"",
|
||||
f"<{pager.prev(request, ['limit'])}>; rel=\"prev\"",
|
||||
)
|
||||
)
|
||||
response.headers["Link"] = pager.link_header(request, ["limit"])
|
||||
|
||||
return [
|
||||
event.to_mastodon_status_json(interactions=interactions)
|
||||
|
@ -79,12 +74,9 @@ def public(
|
|||
)
|
||||
|
||||
if pager.results:
|
||||
params = ["limit", "local", "remote", "only_media"]
|
||||
response.headers["Link"] = ", ".join(
|
||||
(
|
||||
f'<{pager.next(request, params)}>; rel="next"',
|
||||
f'<{pager.prev(request, params)}>; rel="prev"',
|
||||
)
|
||||
response.headers["Link"] = pager.link_header(
|
||||
request,
|
||||
["limit", "local", "remote", "only_media"],
|
||||
)
|
||||
|
||||
interactions = PostInteraction.get_post_interactions(
|
||||
|
@ -123,12 +115,9 @@ def hashtag(
|
|||
)
|
||||
|
||||
if pager.results:
|
||||
params = ["limit", "local", "hashtag", "only_media"]
|
||||
response.headers["Link"] = ", ".join(
|
||||
(
|
||||
f'<{pager.next(request, params)}>; rel="next"',
|
||||
f'<{pager.prev(request, params)}>; rel="prev"',
|
||||
)
|
||||
response.headers["Link"] = pager.link_header(
|
||||
request,
|
||||
["limit", "local", "remote", "only_media"],
|
||||
)
|
||||
|
||||
interactions = PostInteraction.get_post_interactions(
|
||||
|
|
Loading…
Reference in New Issue