These are my models in the models.py file.
class User(AbstractUser):
date_of_birth = models.DateField(blank=True, null=True)
bio = models.TextField(blank=True, null=True)
job = models.CharField(max_length=250, blank=True, null=True)
photo = models.ImageField(upload_to='account_images/',blank=True, null=True)
phone = models.CharField(max_length=11, blank=True, null=True)
followings = models.ManyToManyField('self', through='Contact', related_name='followers', symmetrical=False)
def get_absolute_url(self):
return reverse('social:user_detail', args=[self.username])
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_posts')
description = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
tags = TaggableManager(blank=True)
likes = models.ManyToManyField(User, related_name='liked_post', blank=True)
saved_by = models.ManyToManyField(User, related_name='saved_post', blank=True)
total_likes = models.PositiveIntegerField(default=0)
class Meta:
ordering = ['-created']
indexes = [
models.Index(fields=['-created'])
]
def __str__(self):
return self.author.username
def get_absolute_url(self):
return reverse('social:post_detail', args=[self.id])
class UserActivity(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_activity')
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='post_activity', blank=True, null=True)
action = models.CharField(max_length=50)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.user} {self.action} {self.post.author}' post"
I want to write a signal in which when a user likes a post, an object of the UserActivity model is created, and the value of the user field is set to the user who liked it. The post field should be set to the post that the user liked. And the action field should be set to 'likes'.
@receiver(post_save, sender=Post.likes.through)
def create_like_activity(sender, instance, **kwargs):
if instance.likes.exists():
UserActivity.objects.create(
user=instance.likes.last(),
post=instance.author,
action='likes'
)
I tried to achieve this through this approach, but it didn't work out. I'm relatively new to this and still at a beginner level in many concepts. I would appreciate your guidance.
You are listening to a wrong signal.
Instead you should be listening to m2m_changed signal.
Beware, this signal is fired/sent multiple times
You can check when this signal is fired by checking
action.Action:
So, your code should look like this: