Skip to content

Commit

Permalink
feat: show recommendations in discover page
Browse files Browse the repository at this point in the history
  • Loading branch information
danjac committed Jan 20, 2025
1 parent fc01768 commit 71780d5
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 55 deletions.
46 changes: 11 additions & 35 deletions radiofeed/podcasts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.contrib.postgres.search import SearchVectorField
from django.core.validators import MinLengthValidator
from django.db import models
from django.db.models.functions import Coalesce, Lower
from django.db.models.functions import Lower
from django.urls import reverse
from django.utils import timezone
from django.utils.encoding import force_str
Expand Down Expand Up @@ -139,42 +139,18 @@ def recommended(self, user: User) -> models.QuerySet["Podcast"]:
"""Returns recommended podcasts for user based on subscriptions. Includes `relevance` annotation.
Backfills results with promoted podcasts if no recommendations are found.
"""

# pick highest matches
# we want the sum of the relevance of the recommendations, grouped by recommended

scores = (
Recommendation.objects.alias(
is_podcast_subscribed=models.Exists(
user.subscriptions.filter(
podcast=models.OuterRef("podcast"),
)
return (
self.alias(
score=models.Sum("similar__score"),
relevance=models.Case(
models.When(score__gt=0, then=models.F("score")),
models.When(promoted=True, then=models.Value(1.0)),
default=models.Value(0),
output_field=models.DecimalField(decimal_places=10, max_digits=100),
),
is_recommended_subscribed=models.Exists(
user.subscriptions.filter(
podcast=models.OuterRef("recommended"),
)
),
)
.filter(
is_podcast_subscribed=True,
is_recommended_subscribed=False,
recommended=models.OuterRef("pk"),
)
.values("score")
.order_by("-score")
)

return self.annotate(
relevance=Coalesce(
models.Subquery(
scores.values("score")[:1],
),
0,
output_field=models.DecimalField(),
),
).filter(
models.Q(relevance__gt=0) | models.Q(promoted=True),
.exclude(pk__in=user.subscriptions.values("podcast"))
.filter(relevance__gt=0)
)


Expand Down
7 changes: 5 additions & 2 deletions radiofeed/podcasts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ def discover(request: HttpRequest) -> HttpResponse:
"""Shows all promoted podcasts."""
podcasts = (
_get_podcasts()
.filter(promoted=True)
.order_by("-pub_date")[: settings.DEFAULT_PAGE_SIZE]
.recommended(request.user)
.order_by(
"-relevance",
"-pub_date",
)[: settings.DEFAULT_PAGE_SIZE]
)

return render(
Expand Down
34 changes: 16 additions & 18 deletions templates/podcasts/discover.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,20 @@
{% endblock title %}

{% block content %}
{% cache 300 discover-podcasts %}
<c-header title="Discover">
<c-header.nav>
<c-header.nav.item>
<c-search.form url="{% url 'podcasts:search_podcasts' %}"
placeholder="Search: Podcasts"
/>
</c-header.nav.item>
</c-header.nav>
</c-header>
<c-browse>
{% for podcast in podcasts %}
<c-browse.item>
<c-podcasts.podcast :podcast="podcast" />
</c-browse.item>
{% endfor %}
</c-browse>
{% endcache %}
<c-header title="Discover">
<c-header.nav>
<c-header.nav.item>
<c-search.form url="{% url 'podcasts:search_podcasts' %}"
placeholder="Search: Podcasts"
/>
</c-header.nav.item>
</c-header.nav>
</c-header>
<c-browse>
{% for podcast in podcasts %}
<c-browse.item>
<c-podcasts.podcast :podcast="podcast" />
</c-browse.item>
{% endfor %}
</c-browse>
{% endblock content %}

0 comments on commit 71780d5

Please sign in to comment.