I’m working on a Django project and I’m trying to calculate the total number of likes for a user based on their posts (i.e if a user has post with 10 likes and another with 5, the total likes must display 15) . I’ve tried various approaches, but I haven’t been able to get it working.
Here is my models.py:
class User(AbstractUser):
username = models.CharField(...)
first_name = models.CharField(...)
last_name = models.CharField(...)
email = models.EmailField(...)
bio = models.CharField(...)
...
class Post(models.Model):
author = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
text = models.CharField(max_length=280)
created_at = models.DateTimeField(auto_now_add=True)
likes = models.ManyToManyField(User, related_name="user_post")
def total_likes(self):
return self.likes.count()
class Meta:
ordering = ["created_at"]
And here I am trying to display the total number of likes for all posts from a specific user inside this html file (user profile):
...
<p>Total likes: {{ post.likes.all.count }} </p>
...
views.py
@login_required
def show_user(request, user_id):
try:
user = User.objects.get(id=user_id)
posts = Post.objects.filter(author=user)
except ObjectDoesNotExist:
return redirect('user_list')
else:
return render(request, 'show_user.html', {'user': user , 'posts' : posts, 'request_user': request.user})
Here’s what I’ve tried so far:
-
Initially, I attempted to use the
{{ post.likes.all.count }}template tag to display the total number of likes for each post. However, this didn’t work as it didn’t return any value on the screen. -
Next, I tried using the {% add %} template tag within a loop to iterate over all the posts and accumulate the likes count. However, this resulted in a TemplateSyntaxError.
I am not sure what the best way to solve this issue is. I would greatly appreciate any guidance or suggestions on how to calculate and display the total number of likes for a user’s from all posts in Django.
>Solution :
You can determine the total number of likes for an author with:
from django.db.models import Count
@login_required
def show_user(request, user_id):
user = get_object_or_404(
User.objects.annotate(total_likes=Count('post__likes')), pk=user_id
)
posts = Post.objects.filter(author=user)
return render(
request,
'show_user.html',
{'user': user, 'posts': posts, 'request_user': request.user},
)
in the template you can then render the total likes of the user with:
{{ user.total_likes }}
You can also boost counting the number of likes per post with:
from django.db.models import Count
@login_required
def show_user(request, user_id):
user = get_object_or_404(
User.objects.annotate(total_likes=Count('post__likes')), pk=user_id
)
posts = Post.objects.annotate(num_likes=Count('likes')).filter(author=user)
return render(
request,
'show_user.html',
{'user': user, 'posts': posts, 'request_user': request.user},
)
In the template you can then render this with:
{% for post in posts %}
{{ post }} (likes: {{ post.num_likes }})
{% endfor %}
Note: It is often better to use
get_object_or_404(…)[Django-doc],
then to use.get(…)[Django-doc] directly. In case the object does not exists,
for example because the user altered the URL themselves, theget_object_or_404(…)will result in returning a HTTP 404 Not Found response, whereas using
.get(…)will result in a HTTP 500 Server Error.
Note: It is normally better to make use of the
settings.AUTH_USER_MODEL[Django-doc] to refer to the user model, than to use theUsermodel [Django-doc] directly. For more information you can see the referencing theUsermodel section of the documentation.