我做了一个下面给出的投票模型。我的blog模型有两个操作,即向上投票或向下投票特定的blog。 例如,当一个用户向上投票时,Blog中的“投票”字段会增加,并且UserVote模型有一个记录;当同一个用户向下投票时,它会更改其投票类型并更新记录
当第二个用户投票时,问题就出现了。在upvote之后,当第二个用户downvote时,它表示他已经投票了(尽管它应该将他的投票类型改为downvote)
我一直在处理这个问题,但在任何地方都找不到解决办法
class Blog(models.Model):
title = models.CharField(max_length=100, blank=True, default='')
description = models.TextField(max_length=1500)
created = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey('auth.User', related_name='blog', on_delete=models.CASCADE, null=True)
image = models.FileField(blank=True, null=True)
votes = models.IntegerField(default=0)
def upvote(self, user):
try:
if UserVote.objects.filter(user=user, blog=self, vote_type='down').exists():
self.post_votes.update(user=user, blog=self, vote_type='up')
self.votes += 2
else:
self.post_votes.create(user=user, blog=self, vote_type='up')
self.votes += 1
self.save()
except IntegrityError:
return 'already_voted'
return 'ok'
def downvote(self, user):
try:
if UserVote.objects.filter(user=user, blog=self, vote_type='up').exists():
self.post_votes.update(user=user, blog=self, vote_type='down')
self.votes -= 2
else:
self.post_votes.create(user=user, blog=self, vote_type='down')
self.votes -= 1
self.save()
except IntegrityError:
return 'already_voted'
return 'ok'
class UserVote(models.Model):
user = models.ForeignKey('auth.User', related_name='user_votes', on_delete=models.CASCADE)
blog = models.ForeignKey(Blog, related_name='post_votes', on_delete=models.CASCADE)
vote_type = models.CharField(max_length=10)
class Meta:
unique_together = ('user', 'blog', 'vote_type')
问题产生于这样一个事实,即每个用户/Blog/VoteType组合可以有一个UserVote对象
具体来说,在以下几行中
您正在尝试将当前博客的所有投票对象更新为投票类型之一。这意味着您可能会尝试修改两个UserVotes,使其具有完全相同的用户、博客和投票类型,从而导致IntegrityError
因此,我建议每个用户/Blog组合只能有一个UserVote,而不是每个用户/Blog/VoteType组合,也就是说,将unique\u一起更改为
然后,如果用户已经在博客上投票了,您只需更改投票类型。这可以防止同一个用户同时对同一个博客投赞成票和反对票
此外,您不必手动跟踪向上投票和向下投票的总数,您可以直接从UserVote对象的计数中获得它们。我建议的models.py如下所示:
我确信有一种更聪明的方法可以使用aggregations来获得总的赞成票和反对票,这只是一个简单的例子
相关问题 更多 >
编程相关推荐