Написание сигнала Django для регистрации действий пользователя в модели

Вот мои модели в файле 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, а значение поля user устанавливается на пользователя, которому он понравился. Поле post должно быть установлено в значение поста, который понравился пользователю. А поле action должно быть установлено в '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'
        )

Я пытался добиться этого с помощью данного подхода, но у меня ничего не вышло. Я относительно новичок в этом деле и все еще нахожусь на уровне новичка во многих концепциях. Буду признателен за ваши рекомендации.

Вы слушаете неправильный сигнал.

Вместо этого вы должны слушать сигнал m2m_changed.

Осторожно, этот сигнал подается/отправляется несколько раз

"pre_add" Отправляется до добавления одного или нескольких объектов в отношение.

"post_add" Отправляется после добавления одного или нескольких объектов в отношение.

"pre_remove" Отправляется перед удалением одного или нескольких объектов из

.

отношения. "post_remove" Отправляется после удаления одного или нескольких объектов

из отношения. "pre_clear" Отправляется перед очисткой отношения.

"post_clear" Отправляется после очистки отношения.

Вы можете проверить, когда сработает этот сигнал, проверив 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'
        )
Вернуться на верх