编写Django信号记录模型中的用户活动

0 投票
1 回答
24 浏览
提问于 2025-04-12 13:39

这是我在models.py文件中的模型。

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"

我想写一个信号,也就是说,当用户点赞一篇帖子时,就会创建一个UserActivity模型的对象,并把用户字段设置为点赞的用户。帖子字段应该设置为用户点赞的帖子。而动作字段应该设置为'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'
        )

我尝试通过这种方法来实现,但没有成功。我对这些内容还比较陌生,很多概念还处于初学者水平。希望能得到你的指导。

1 个回答

0

你现在关注的信号是错误的。

你应该关注的是 m2m_changed 信号。

要注意,这个信号会被触发多次。

“pre_add” 是在一个或多个对象被添加到关系之前发送的。

“post_add” 是在一个或多个对象被添加到关系之后发送的。

“pre_remove” 是在一个或多个对象从关系中移除之前发送的。

“post_remove” 是在一个或多个对象从关系中移除之后发送的。

“pre_clear” 是在关系被清空之前发送的。

“post_clear” 是在关系被清空之后发送的。

你可以通过检查 action 来了解这个信号何时被触发。

动作:

action 是一个字符串,表示对关系所做的更新类型。

所以,你的代码应该像这样:


@receiver(m2m_changed, sender=Post.likes.through)
def create_like_activity(sender, instance, action, **kwargs):
    if instance.likes.exists() and action == "post_add":
        UserActivity.objects.create(
            user=instance.likes.last(),
            post=instance,
            action='likes'
        )

撰写回答