首页 > 解决方案 > 如何正确使用 dispatch_uid 避免重复信号

问题描述

你好,

我正在尝试使用 a 来应用dispatch_uid="my_unique_identifier",以避免在我的项目中发送重复的信号。

我搜索了几个类似的答案并阅读了以下文档,但我不确定我缺少什么:

https://docs.djangoproject.com/en/3.1/topics/signals/#preventing-duplicate-signals

在我的项目中,有作者撰写的帖子,每个帖子都有一个点赞按钮,当用户点击该按钮时,通知会创建并发送给作者。

直到这里一切都很好,除了发送 2 个通知而不是 1 个。我尝试了以下但没有任何效果,我仍然收到 2 个通知

所以这里是:

这是Like model.py

class Like(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    value = models.CharField(choices=LIKE_CHOICES, default='Like', max_length=8)

    def user_liked_post(sender, instance, *args, **kwargs):
        like = instance
        if like.value=='Like':
            post = like.post
            sender = like.user
            dispatch_uid = "my_unique_identifier"
            notify = Notification(post=post, sender=sender, user=post.author, notification_type=1)
            notify.save()

post_save.connect(Like.user_liked_post, sender=Like, dispatch_uid="my_unique_identifier")

这是通知模型

class Notification(models.Model):
    NOTIFICATION_TYPES=((1,'Like'),(2,'Comment'),(3,'Admin'))

    post = models.ForeignKey('blog.Post', on_delete=models.CASCADE, related_name="noti_post", blank=True, null=True)
    sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="noti_from_user")
    user = models.ForeignKey(User, on_delete=models.CASCADE,related_name="noti_to_user")
    notification_type= models.IntegerField(choices=NOTIFICATION_TYPES)

    def __str__(self):
        return str(self.post)

这是views.py:

def LikeView(request):
    post = get_object_or_404(Post, id=request.POST.get('id'))
    liked = False
    current_likes = post.num_likes
    user = request.user
    if post.author.id == request.user.id:
        messages.warning(request, 'You can not like you own Post')
    else:
        if post.likes.filter(id=request.user.id).exists():
            post.likes.remove(request.user)
            liked = False
            current_likes = current_likes - 1
        else:
            post.likes.add(request.user)
            liked = True
            current_likes = current_likes + 1
        post.num_likes = current_likes
        post.save()

        like, created = Like.objects.get_or_create(user=user, post=post)
        sender = like.user

        if not created:
            if like.value == 'Like':
                like.value = 'Unlike'
                like.delete_notification(sender, post)
            else:
                like.value = 'Like'
        like.save()

    context = {
        'total_likes': post.total_likes,
        'liked': liked,
        'post': post,
    }
    if request.is_ajax:
        html = render_to_string('blog/like_section.html', context, request=request)
        return JsonResponse({'form': html})

更新:

这是我试图替换 get_or_create: 但得到的AttributeError: 'Like' object has no attribute 'exists'

    try:
        like = Like.objects.filter(user=user, post=post)
        sender = like.user

        if like.exists():
            like.delete()
            like.delete_notification(sender,post)  

        else:
            like = Like(user=user, post=post)
            like.save()
    except Like.DoesNotExist:
        like = Like(user=user, post=post)

        if like.value == 'Like':
            like.value = 'Unlike'
            like.delete_notification(sender, post)
        else:
            like.value = 'Like'
        like.save()

我的问题是如何正确使用 dispatch_uid="my_unique_identifier" 以避免重复信号?

标签: pythondjangodjango-signals

解决方案


您创建了喜欢并再次保存了它。这就是为什么:

like, created = Like.objects.get_or_create(user=user, post=post)

like.save()

get_or_create意思如下:

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()

因为在你的情况下,每次点击喜欢,它都是一个新对象(我想)?然后,get_or_create将转到exceptsave()。所以你节省了两次。

以下可能会解决您在评论中提到的like->unlike->like的问题。

代替:

        like, created = Like.objects.get_or_create(user=user, post=post)
        sender = like.user

        if not created:
            if like.value == 'Like':
                like.value = 'Unlike'
                like.delete_notification(sender, post)
            else:
                like.value = 'Like'
        like.save()

try:
    
    like =Like.objects.get(user=user, post=post)
    like.delete() 
    like.delete_notification(sender, post) # this part seems weird, you did not define ```sender``` in this view. 

except Like.DoesNotExist:
     like = Like(user=user, post=post)
     like.save()


推荐阅读