Home > Net >  Display counter of likes per post with Django is not working
Display counter of likes per post with Django is not working

Time:12-16

I want to get a variable on the views.py file that retrieves the list of likes for each post. So, then on the HTML file, I would use .count so I can get the number of items on the list and finally be displayed on the DOM.

I first made classes on models.py. There, I have 3 classes: User, Post, and Like. User is from the default User class from Django. Post is a class that gets information about the post like the author, description, and timestamp. And on the Like class, I get the user and post.

from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    pass

class Post(models.Model):
    author = models.ForeignKey("User", on_delete=models.CASCADE, related_name="user")
    description = models.CharField(max_length=1000)
    timestamp = models.DateTimeField(auto_now_add=True)
    def __str__(self):
        return f"{self.id}: {self.author}"

class Like (models.Model):
    user = models.ForeignKey("User", on_delete=models.CASCADE, default='', related_name="user_like")
    post = models.ForeignKey("Post", on_delete=models.CASCADE, default='', related_name="post_like")
    def __str__(self):
        return f"{self.id}:{self.user} likes {self.post}"

Second, I made a function on views.py called "index". There, I get the whole list of posts (on the posts variable), then I tried to create the variable (totalLikesSinglePost), which should get the list of likes for each post.

def index(request):
    posts = Post.objects.all().order_by("id").reverse()

    # Pagination Feature (OMIT THIS, IF YOU WANT)
    p = Paginator(posts, 10)
    pageNumber = request.GET.get('page')
    postsPage = p.get_page(pageNumber)

    # Total likes of each post. DOESN'T WORK ⏬
    for postSingle in posts: 
        totalLikesSinglePost = Like.objects.all().filter(post = postSingle)

    return render(request, "network/index.html", {
        "posts": posts,
        "postsPage": postsPage,
        "totalLikesPost": totalLikesSinglePost
    })

Finally, on the HTML file, there I get each post with its information and the number of likes. However, the output just displays the number 0

    {% for post in postsPage %}
    <div >
        <div >
            <div  id="post-grid">
                <div >
                    <h5>{{ post.author }}</h5>
                    <div> | {{ post.timestamp }}</div>
                    <p>{{ post.description }}</p>
                    <div >
                        <strong style="color: red">{{ totalLikesPost.count }}</strong> <!--0 IS DISPLAYED-->
                    </div>
                </div>
            </div>
        </div>
    </div>
    {% endfor %}    

And of course, after that, I created a superuser and went to admin to add some examples to the database. However, I added some new rows on the Like table but does not display the total of likes for each post.

CodePudding user response:

Your totalLikesSinglePost is just a list of Like records of the last post. Try this on your html file:

<strong style="color: red">{{ post.post_like.count }}</strong>

CodePudding user response:

Because totalLikesSinglePost get override in each round of for loop. It is the total number of likes of the last post.

You need to assign this number to the post as an attribute, like

for post in posts:
    post.num_likes = Like.objects.all().filter(post=post).count()

And then in your template

{% for post in posts %}
    {# ... #}
    {{ post.num_likes }}
{% endfor %}

However, I strongly recommend you using .annotate

from django.db.models import Count

posts = Post.objects.all().order_by('-id')\
    .annotate(num_likes=Count('like'))

This will access database only once and save you a lot of time.

  • Related