makz
makz

Reputation: 97

how to fix sql query in django

I'm not sure how to fix 'likesCounter' query. I want to count all likes from one article. Any help is appreciated.

enter image description here'

model:

class Likes(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name="like_article")
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='liker_user')

view:

def article_detail(request, pk):
    article = Article.objects.get(pk=pk)
    already_liked = Likes.objects.filter(article=article, user=request.user)
    likesCounter = Likes.objects.filter(article=article, user_id=request.user).count()
    if already_liked:
        liked = True
    else:
        liked = False
    return render(request, 'article/single-article.html', context={'article':article, 'liked': liked,'likesCounter':likesCounter,'already_liked':already_liked})

Upvotes: 1

Views: 57

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477804

You should drop the filter where you filter on the user id, so:

#                  no user_id=request.user ↓
likesCounter = Likes.objects.filter(article=article).count()

You can however combine the tree items in a single query with:

from django.db.models import Count, Exists, OuterRef
from django.shortcuts import get_object_or_404

def article_detail(request, pk):
    qs = Article.objects.annotate(
        likes=Count('like_article'),
        is_liked=Exists(
            Like.objects.filter(article=OuterRef('pk'), user=request.user)
        )
    )
    article = get_object_or_404(qs, pk=pk)
    already_liked = article.is_liked
    likesCounter = likes
    return render(request, 'article/single-article.html', context={'article':article, 'liked': liked,'likesCounter':likesCounter,'already_liked':already_liked})

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, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using .get(…) will result in a HTTP 500 Server Error.

Upvotes: 1

Related Questions