Here is a project I've created to practice, in my models.py,
class Post(models.Model):
title = models.CharField(max_length = 140)
author = models.ForeignKey(User, on_delete=models.CASCADE)
votes = models.BigIntegerField(default=0, blank=True)
class Vote(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='voter')
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='vpost')
@receiver(post_save, sender=Vote)
def update_votes(sender, **kwargs):
# # ??
Here I have a Voteform with that user can vote any particular post. That part works well.
Here is my question, whenever a user votes a particular post, I want votes field in Post model to increase as well.
I know I can show it with {{post.vpost.count}} in my html. But I want that increment here.
Other way I have tried,
class Vote(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='voter')
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='vpost')
def update_votes(self):
p = self.post
p.votes += 1
p.save()
This one only works once, not working from second time, so I want to use signal method. So how can I update the vote field in Post model using signal?
Nearly there. I would rename Post.votes
to Post.votes_count
as votes
indicates a reverse relationship.
@receiver(post_save, sender=Vote)
def update_votes(sender, instance, **kwargs):
post = instance.post
post.votes_count += 1
post.save()
Although you might want to make sure that the count is correct, by introducing another query:
@receiver(post_save, sender=Vote)
def update_votes(sender, instance, **kwargs):
post = instance.post
post.votes_count = post.votes_set.all().count()
post.save()
You might also want to do this when/if a Vote
is deleted to make sure the count is correct.
Bear in mind you could also just do this in the Vote
's save
method instead of needing signals.
You could also do this as a cronjob or task depending on your circumstances