导致未知问题的投票模型操作

2024-05-06 01:33:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我做了一个下面给出的投票模型。我的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')

Tags: 用户模型selftruereturnmodelstypeblog
1条回答
网友
1楼 · 发布于 2024-05-06 01:33:39

问题产生于这样一个事实,即每个用户/Blog/VoteType组合可以有一个UserVote对象

具体来说,在以下几行中

self.post_votes.update(user=user, blog=self, vote_type='up')

self.post_votes.update(user=user, blog=self, vote_type='down')

您正在尝试将当前博客的所有投票对象更新为投票类型之一。这意味着您可能会尝试修改两个UserVotes,使其具有完全相同的用户、博客和投票类型,从而导致IntegrityError

因此,我建议每个用户/Blog组合只能有一个UserVote,而不是每个用户/Blog/VoteType组合,也就是说,将unique\u一起更改为

unique_together = ('user', 'blog')

然后,如果用户已经在博客上投票了,您只需更改投票类型。这可以防止同一个用户同时对同一个博客投赞成票和反对票

此外,您不必手动跟踪向上投票和向下投票的总数,您可以直接从UserVote对象的计数中获得它们。我建议的models.py如下所示:

from django.db import models


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)

    @property
    def votes(self):
        upvotes = UserVote.objects.filter(blog=self, vote_type='up').count()
        downvotes = UserVote.objects.filter(blog=self, vote_type='down').count()
        return upvotes - downvotes

    def upvote(self, user):
        vote, created = UserVote.objects.get_or_create(user=user, blog=self)
        if not created and vote.vote_type == 'up':
            return 'already_voted'
        vote.vote_type = 'up'
        vote.save()
        return 'ok'

    def downvote(self, user):
        vote, created = UserVote.objects.get_or_create(user=user, blog=self)
        if not created and vote.vote_type == 'down':
            return 'already_voted'
        vote.vote_type = 'down'
        vote.save()
        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')

我确信有一种更聪明的方法可以使用aggregations来获得总的赞成票和反对票,这只是一个简单的例子

相关问题 更多 >