为项目添加投票功能:解决重复投票检测、存储及视图报错问题
投票功能实现问题
我正在为项目添加投票功能,当前需实现用户单次投票功能,面临以下问题:
- 如何检测用户是否已对某个Answer投过票;
- 如何将投票数据(关联Answer与User)存入数据库;
- 现有视图代码报错:
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
相关产品推荐
相关产品推荐

