Django用户唯一点赞按钮异常:重复点击致重复计数问题
问题分析与解决方案
核心问题定位
你的点赞重复计数问题根源在TweetLike模型的错误字段设置,导致数据库层面的唯一性约束逻辑混乱:
liker字段设置了unique=True,这会强制一个用户只能创建一条点赞记录,意味着用户只能给某一条推文点赞,完全违背多推文点赞的需求。like_count字段设置了unique=True,该字段全局唯一的约束毫无意义,还会引发数据库报错。- 虽然你设置了
unique_together = ('tweet', 'liker'),但liker的unique=True会覆盖联合约束的作用,导致逻辑冲突。
修复步骤
1. 修正TweetLike模型
修改models.py中的TweetLike类,移除错误的unique设置,保留联合唯一约束:
# Tweet Like # -------------- class TweetLike(models.Model): creation_date = models.DateField(default=timezone.now) id = models.AutoField(primary_key=True) tweet = models.ForeignKey( Tweet, on_delete=models.CASCADE, blank=True, null=True ) liker = models.ForeignKey( BasicUserProfile, on_delete=models.CASCADE, blank=True, null=True # 移除 unique=True 约束 ) # 移除 like_count 字段,无需单独存储该值 class Meta: unique_together = ('tweet', 'liker') # 保留该约束,确保单用户对单推文仅能创建一条点赞记录 def __str__(self): return f"Like id: {self.id}"
2. 优化视图逻辑
视图中判断用户是否已点赞时,使用exists()方法更高效清晰,同时确保计数逻辑准确:
if request.POST.get("single_tweet_like_submit_btn"): try: print(f"Request by user: {current_basic_user_profile.user.username} for tweet ID: {current_tweet.id}") # 改用exists()判断是否已点赞,性能更优 has_liked = TweetLike.objects.filter(tweet=current_tweet, liker=current_basic_user_profile).exists() if has_liked: print(f"User {current_basic_user_profile.user.username} has already liked tweet {current_tweet.id}, unliking it.") # 删除该用户对这条推文的点赞(联合唯一约束确保仅存在一条记录) TweetLike.objects.filter(tweet=current_tweet, liker=current_basic_user_profile).delete() current_tweet.tweet_like_amount = max(0, current_tweet.tweet_like_amount - 1) else: print(f"User {current_basic_user_profile.user.username} has not liked tweet {current_tweet.id}, liking it.") new_like = TweetLike(tweet=current_tweet, liker=current_basic_user_profile) new_like.save() current_tweet.tweet_like_amount += 1 new_notification = NotificationLike( notified=current_tweet.user, notifier=current_basic_user_profile, tweet=current_tweet, ) new_notification.save() current_tweet.save() print(f"Tweet {current_tweet.id} now has {current_tweet.tweet_like_amount} likes.") except Exception as e: print(f"An error occurred: {e}") return HttpResponseRedirect(f"/tweet/{current_tweet.id}/")
3. 可选优化:避免手动维护点赞数
手动维护tweet_like_amount容易出现计数不一致的情况,建议通过关联查询实时获取点赞数,在Tweet模型中添加属性:
class Tweet(models.Model): # 你的其他字段... tweet_like_amount = models.IntegerField(default=0) # 可保留,但推荐用下面的属性替代 @property def real_like_count(self): return self.tweetlike_set.count()
在模板中使用{{ tweet.real_like_count }}即可获取准确的点赞数,无需手动维护计数。
最后操作
修改模型后,执行数据库迁移命令:
python manage.py makemigrations python manage.py migrate
内容的提问来源于stack exchange,提问作者Abol
相关产品推荐
相关产品推荐

