2

I'm using django-activity-stream to create a feed of goals. A simplified version of Goal object is as follows:

class Goal(models.Model):
    user = models.ForeignKey(User, related_name="goals", on_delete=models.CASCADE)
    liked_by = models.ManyToManyField(User, related_name="goals_cheered")
    title = models.CharField(_("title"), max_length=80)

There are 2 actions in place: the goal should appear in the feed once it's created and once it has been completed. Then users can like the goal, and here's where I'm stuck: adding the 'likes' count on the feed.

This was the (failed) attempt that made the most sense to me so far:

from django.db.models import Prefetch

goal_qs = Goal.objects.annotate(likes=Count("liked_by"))
prefetch = [Prefetch("action_object", queryset=goal_qs)]

# in a `group` feed:
qs = group.target_actions.all().prefetch_related("actor__profile").prefetch_related(*prefetch)

This gives me a ValueError: "Custom queryset can't be used for this lookup." Maybe it's because django-activity-stream uses GFKs?

How can I get a count of likes? Can I limit the content_type somehow?

Update

Managed to get is work by using the {{ goal.liked_by.all|length }} on the template. Not really comfortable with that solution, especially in a ListView. It felt super unoptimized.

Original BBQ Sauce
  • 527
  • 1
  • 11
  • 24

1 Answers1

0

This is indeed sub-optimal. But with generic foreign keys I'm afraid you can't do much better. However, {{ goal.liked_by.count }} would still be much more efficient than {{ goal.liked_by.all|length }}.

Antoine Pinsard
  • 33,148
  • 8
  • 67
  • 87