I want to count number of replies on a particular post in Django
View.py
def forum(request):
profile = Profile.objects.all()
if request.method=="POST":
user = request.user
image = request.user.profile.image
content = request.POST.get('content','')
post = Post(user1=user, post_content=content, image=image)
post.save()
messages.success(request, f'Your Question has been posted successfully!!')
return redirect('/forum')
posts = Post.objects.filter().order_by('-timestamp')
return render(request, "forum.html", {'posts':posts})
Reply code
def discussion(request, myid):
post = Post.objects.filter(id=myid).first()
replies = Replie.objects.filter(post=post)
if request.method=="POST":
user = request.user
image = request.user.profile.image
desc = request.POST.get('desc','')
post_id =request.POST.get('post_id','')
reply = Replie(user = user, reply_content = desc, post=post, image=image)
reply.save()
messages.success(request, f'Your Reply has been posted successfully!!')
return redirect('/forum')
return render(request, "discussion.html", {'post':post, 'replies':replies})
model.py
class Post(models.Model):
user1 = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
post_id = models.AutoField
post_content = models.CharField(max_length=5000)
timestamp= models.DateTimeField(default=now)
image = models.ImageField(upload_to="images",default="")
def __str__(self):
return f'{self.user1} Post'
class Replie(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
reply_id = models.AutoField
reply_content = models.CharField(max_length=5000)
post = models.ForeignKey(Post, on_delete=models.CASCADE, default='')
timestamp= models.DateTimeField(default=now)
image = models.ImageField(upload_to="images",default="")
def __str__(self):
return f'{self.user1} Post'
My Forum.html code:
{% for post in posts %}
<div >
<div >
<div >
<div >
<div >
<div > <img src="/media/{{post.image}}"
alt="profileimage"style="width: 40px;height: 40px;"> <p > {{post.user1}} </p>
<div > <a href="/discussion/{{post.id}}" data-abc="true"><button style="color:blue; font-size: 13px;">Add or See reply </button> </a>
</div>
<div >
<div >Nmber of reply {{post.timestamp}} </div>
</div>
{% if user.is_superuser or user.is_staff %}
<a href="{% url 'dashboard:delete_post' post.id %}"> <button onclick="window.mytest()">Delete Post</button></a>
<script type="text/javascript">window.mytest = function() { var isValid = confirm('If you click ok then its delete this post and related reply on it. Are you sure to delete?');if (!isValid) { event.preventDefault(); alert("It wont delete. Yay!");}}</script>
{% endif %}
</div>
</div>
<div >
<p>{{post.post_content}}</p>
</div>
<div >
</div>
</div>
</div>
</div>
</div>
{% endfor %}
I want to do like this
where on the place of Number of reply, I want to display the number of replies of the particular post
CodePudding user response:
To archive this you can use the related name of the Post
model (have a look at the documentation). Django will create a field for every foreign key that allows you to access the related model. By default, this will be named replie_set
on the Post
model.
This field you can then use to get the number of replies to a post by calling the count()
method of the replie_set
queryset. I would also add a method to the Post
model that does that for you as a convenience.
To bring this together, your Post
model would look like this:
class Post(models.Model):
user1 = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
post_id = models.AutoField
post_content = models.CharField(max_length=5000)
timestamp= models.DateTimeField(default=now)
image = models.ImageField(upload_to="images",default="")
@property
def count_replies():
return self.replies_set.count()
def __str__(self):
return f'{self.user1} Post'
Assuming that your forum.html
template iterates over the posts like that:
{% for post in posts %}
...
<p>Posts: {{ post.count_replies }}</p>
...
{% endfor %}
You get the number of replies by calling post.count_replies()
. Of course, if you don't want to add a dedicated method to the model you can just use do post.replie_set.count()
directly.
CodePudding user response:
@Eega suggested the right answer just some changes in the code will help you
class Post(models.Model):
user1 = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
post_id = models.AutoField
post_content = models.CharField(max_length=5000)
timestamp= models.DateTimeField(default=now)
image = models.ImageField(upload_to="images",default="")
@property
def count_replies(self):
return self.replie_set.count()
def __str__(self):
return f'{self.user1} Post'
post = Post.objects.filter(id=myid).first()
to post = Post.objects.filter(id=myid).first().prefetch_related('replies_set')
This will make your query optimized
Also accept @Eega answer only, I have just showed you the edited code
Now I am suggesting one good method here
Post.objects.get(id=myid).annotate(post_count=Count("replie"))
Simply use this in your views without changing #models.py and access it in your template as post.post_count in for loop.