feat(blog): add recommended posts endpoint
This commit is contained in:
@@ -357,6 +357,47 @@ def list_posts(
|
||||
return list(queryset[offset : offset + limit])
|
||||
|
||||
|
||||
@blog_router.get("/posts/{slug}/recommended", response=List[PostListSchema])
|
||||
def recommended_posts(request, slug: str, limit: int = Query(3, ge=1, le=12)):
|
||||
post = get_object_or_404(
|
||||
Post.objects.select_related("category").prefetch_related("tags"),
|
||||
slug=slug,
|
||||
status=Post.StatusChoices.PUBLISHED,
|
||||
)
|
||||
tag_ids = list(post.tags.values_list("id", flat=True))
|
||||
selected = []
|
||||
seen_ids = {post.id}
|
||||
|
||||
def append_posts(queryset):
|
||||
remaining = limit - len(selected)
|
||||
if remaining <= 0:
|
||||
return
|
||||
for candidate in queryset.exclude(id__in=seen_ids)[:remaining]:
|
||||
selected.append(candidate)
|
||||
seen_ids.add(candidate.id)
|
||||
|
||||
if tag_ids:
|
||||
append_posts(
|
||||
_published_queryset()
|
||||
.filter(tags__id__in=tag_ids)
|
||||
.annotate(shared_tags=Count("tags", filter=Q(tags__id__in=tag_ids), distinct=True))
|
||||
.order_by("-shared_tags", "-published_at", "-created_at")
|
||||
.distinct()
|
||||
)
|
||||
|
||||
if len(selected) < limit and post.category_id:
|
||||
append_posts(
|
||||
_published_queryset()
|
||||
.filter(category_id=post.category_id)
|
||||
.order_by("-published_at", "-created_at")
|
||||
)
|
||||
|
||||
if len(selected) < limit:
|
||||
append_posts(_published_queryset().order_by("-published_at", "-created_at"))
|
||||
|
||||
return selected
|
||||
|
||||
|
||||
@blog_router.get("/posts/{slug}", response=PostDetailSchema)
|
||||
def get_post(request, slug: str):
|
||||
return get_object_or_404(_published_queryset(), slug=slug)
|
||||
|
||||
Reference in New Issue
Block a user