ebong
ebong

Reputation: 65

Display total number of comments related to each object in a list view

I have a view which displays all my posts. Post has ForeignKey relation with comment.I want to be able to display the total number of comments related to each post in a Listview. Like on facebook feedback one can see the total number of comments on each post display on user activity feed .

Model. py

class Post(models.Model):
   name=models.CharField(max_length=230,null=True)
   text=models.TextArea(null=True)


class Comments(models.Model):
   comment=models.TextArea(null=True)
   post=models.ForeignKey(Post,related_name="post",null=True,on_delete=model.CASCADE)

View.py

def PostListView(request):
#getting  all post objects 
    allpost=Post.objects.all()
#getting all comments 
    allcomments=Comments.objects.all()
    template_name="post.html"
    context={'allpost':allpost,'allcomments':allcomments}
    return render(request,template_name,context)

 def PostDetail(request,slug):
     postinstance=get_object_or_404(Post,slug)
     #getting comments for this post
     comments_for_post=Comments.objects.all().filter(post=postinstance)
     #get the total count for comments for post
     commentcount=comments_for_post.count()

In Listview I want to be able to display the total number of comments related for each post. In Listview template I want something like this:

{% for post in allpost %}
    {{post.name}}
    #get total number of comments for each post
    {{commentcount}}
{% endfor %}

Note I have no problem displaying the total number of comments for a post in DetailView . Please i need help in handling this query

Upvotes: 0

Views: 559

Answers (3)

Zilong Li
Zilong Li

Reputation: 958

You don't have to write any queryset. This can be achieved in your template:

# for big numbers
{% load humanize %}

{% for post in allpost %}
    {{post.name}}
    #get total number of comments for each post
    {{post.post.count|intword}}
{% endfor %}

=======

Optional but recommended: Change the related_name in your Comment model as such:

class Comments(models.Model):
   comment=models.TextArea(null=True)
   post=models.ForeignKey(Post,related_name="comments",null=True,on_delete=model.CASCADE)

Then in the template:

# for big numbers
{% load humanize %}

{% for post in allpost %}
    {{post.name}}
    #get total number of comments for each post
    {{post.comments.count|intword}}
{% endfor %}

Edit: For formating big numbers, add 'django.contrib.humanize' to your INSTALLED_APPS.

Upvotes: 0

AntoineLB
AntoineLB

Reputation: 482

What you need is "group by" SQL equivalent.

from django.db.models import Count
Post.objects.values('post').annotate(dcount=Count('post'))

By the way, in your Comment class, the convention is to code :

   post=models.ForeignKey(Post,related_name="comments",null=True,on_delete=model.CASCADE)

instead of :

   post=models.ForeignKey(Post,related_name="post",null=True,on_delete=model.CASCADE)

Upvotes: 0

Daniel Roseman
Daniel Roseman

Reputation: 599580

You should use an annotation on your Post query.

from django.db.models import Count
allpost = Post.objects.all().annotate(commentcount=Count('post'))

Now you can do {{ post.commentcount }} in your template.

Note, the related_name on your FK to Post makes no sense, the related_name points from Post to Comments so should be called comments. Even better, leave it as the default, which would be comment_set.

Upvotes: 0

Related Questions