You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为项目添加投票功能:解决重复投票检测、存储及视图报错问题

投票功能实现问题

我正在为项目添加投票功能,当前需实现用户单次投票功能,面临以下问题:

  1. 如何检测用户是否已对某个Answer投过票;
  2. 如何将投票数据(关联Answer与User)存入数据库;
  3. 现有视图代码报错:TypeError: 'Answer' object is not subscriptable。

相关代码

模型代码

class Vote(models.Model):
    answer = models.ForeignKey(Answer, on_delete=models.CASCADE, blank=False)
    author = models.ForeignKey(User, on_delete=models.CASCADE, blank=False)

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

class Answer(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='answers')
    answer = models.CharField(max_length=1000, default="", blank=False)
    author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    createdAt = models.DateTimeField(auto_now_add=True)
    votes = models.IntegerField(default=0)

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

序列化器代码

class VoteSerailizer(serializers.ModelSerializer):
    class Meta:
        model = Vote
        fields = '__all__'

视图代码

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def upvote(request, pk):
    answer = get_object_or_404(Answer, id=pk)
    if answer['author'] == request.user:
        return Response({
            'error':"You cannot vote twice."
        })
    answer.votes += 1
    answer.save()
    return Response({
        'details':'Vote added'
    }, status.HTTP_202_ACCEPTED)

问题解决

1. 修复视图报错TypeError: 'Answer' object is not subscriptable

报错原因是用字典索引方式answer['author']访问模型对象属性,Django模型对象的属性需用点.访问,直接改成answer.author即可。

2. 检测用户是否已对该Answer投过票

先给Vote模型添加联合唯一约束,从数据库层面避免重复投票:

class Vote(models.Model):
    answer = models.ForeignKey(Answer, on_delete=models.CASCADE, blank=False)
    author = models.ForeignKey(User, on_delete=models.CASCADE, blank=False)

    class Meta:
        unique_together = ('answer', 'author')  # 强制一个用户对一个回答只能投一次

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

之后在视图中查询是否存在已有投票记录:

has_voted = Vote.objects.filter(answer=answer, author=request.user).exists()
if has_voted:
    return Response({'error': "你已经投过票了"}, status=status.HTTP_400_BAD_REQUEST)

3. 将投票数据存入数据库

确认用户未投票后,创建Vote实例保存,同时更新Answer的票数。修改后的完整视图代码:

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def upvote(request, pk):
    answer = get_object_or_404(Answer, id=pk)
    
    # 可选:禁止作者给自己的回答投票
    if answer.author == request.user:
        return Response({'error': "你不能给自己的回答投票"}, status=status.HTTP_400_BAD_REQUEST)
    
    # 检查是否已投过票
    has_voted = Vote.objects.filter(answer=answer, author=request.user).exists()
    if has_voted:
        return Response({'error': "你已经投过票了"}, status=status.HTTP_400_BAD_REQUEST)
    
    # 保存投票关联数据
    Vote.objects.create(answer=answer, author=request.user)
    
    # 更新回答票数
    answer.votes += 1
    answer.save()
    
    return Response({'details': '投票成功'}, status=status.HTTP_202_ACCEPTED)

内容的提问来源于stack exchange,提问作者Rohit Gajula

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:33:39