Django中Post模型likes字段无法递增问题求助
Django博客点赞功能:Post.likes字段无法递增的解决方案
核心问题:自定义的like方法未被触发
你写的like方法根本没被调用,因为CreateAPIView默认处理POST请求的是create方法,不是你自定义的like方法,所以更新post.likes的代码完全没执行。
修复步骤
1. 覆盖CreateAPIView的post方法
把点赞逻辑放到post方法里,替换默认的create逻辑:
# views.py from rest_framework import status from rest_framework.response import Response from rest_framework import generics, permissions from django.db.models import F from .models import Like, Post from .serializers import LikeSerializer class LikeView(generics.CreateAPIView): permission_classes = [permissions.IsAuthenticated] queryset = Like.objects.all() serializer_class = LikeSerializer def post(self, request, format=None): serializer = self.serializer_class(data=request.data) if serializer.is_valid(): # 从验证后的安全数据中取值,比直接取serializer.data更可靠 user = serializer.validated_data['user'] post = serializer.validated_data['post'] # 先检查是否已点赞,避免重复操作 if Like.objects.filter(user=user, post=post).exists(): return Response({"error": "你已经给这篇帖子点过赞了"}, status=status.HTTP_400_BAD_REQUEST) # 创建点赞记录 like = Like.objects.create(user=user, post=post) # 数据库层面直接递增likes,避免并发计数错误 Post.objects.filter(id=post.id).update(likes=F('likes') + 1) return Response(LikeSerializer(like).data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
2. 修正Like模型的字段与约束
你的Like模型外键命名不合理,还缺少重复点赞的约束:
# models.py from django.db import models from django.contrib.auth.models import User from django.db.models import UniqueConstraint class Post(models.Model): id = models.CharField(max_length=36, default=generate_unique_id, primary_key=True) title = models.CharField(max_length=50) content = models.TextField() likes = models.IntegerField(default=0, blank=True) pub_date = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title class Like(models.Model): # 字段名改为user和post,ForeignKey会自动生成_id后缀,避免混淆 user = models.ForeignKey(User, related_name='user_likes', on_delete=models.CASCADE) post = models.ForeignKey(Post, related_name='post_likes', on_delete=models.CASCADE) class Meta: # 强制一个用户只能给同一篇帖子点一次赞 constraints = [ UniqueConstraint(fields=['user', 'post'], name='unique_user_post_like') ] def __str__(self): return f"{self.user.username} 点赞了 {self.post.title}"
3. 同步修改序列化器字段
因为Like模型字段名改了,序列化器也要对应调整:
# serializers.py from rest_framework import serializers from .models import Like class LikeSerializer(serializers.ModelSerializer): class Meta: fields = ('user', 'post') model = Like
关键优化点
- 用
serializer.validated_data:这是经过序列化器验证后的干净数据,比直接取serializer.data更安全,避免脏数据。 - 数据库层面更新:
Post.objects.filter(id=post.id).update(likes=F('likes') + 1)直接在数据库执行递增,不需要先拉取对象到内存,效率更高,还能避免多个请求同时点赞时的计数错误。 - 重复点赞检查:提前在代码层面判断,避免触发数据库的唯一约束异常,给用户更友好的提示。
内容的提问来源于stack exchange,提问作者user14611431
相关产品推荐
相关产品推荐

