Django:允许用户只投票一次

时间:2018-04-12 19:19:59

标签: django

我希望用户只能投票一次。我知道要创建另一个名为“Vote”的模型来拥有productID和userID,并检查用户是否已经为productID投了一个投票,然后它就不应该upvote。但我不知道如何实现它。

以下是models.py

的一部分
class Product(models.Model):
    title = models.CharField(max_length=255)
    url = models.TextField()
    pub_date = models.DateTimeField()
    votes_total = models.IntegerField(default=1)
    image = models.ImageField(upload_to='image/')
    icon = models.ImageField(upload_to='image/')
    body = models.TextField(max_length=500)
    hunter = models.ForeignKey(User,on_delete=models.CASCADE)

    def __str__(self):
        return self.title

    def pub_date_pretty(self):
        return self.pub_date.strftime('%b %e %Y')

    def summary(self):
        return self.body[:100]

class Vote(models.Model):
    productID = models.ForeignKey(Product,on_delete=models.CASCADE)
    userID = models.ForeignKey(User,on_delete=models.CASCADE)

以下是views.py

的一部分
@login_required
def upvote(request,product_id):
    if request.method == 'POST':
        product = get_object_or_404(Product,pk=product_id)
        product.votes_total += 1
        product.save()
        return redirect('/products/' + str(product.id))

4 个答案:

答案 0 :(得分:0)

在你的upvote方法中,使用productId和userId获取Vote对象。

vote = Vote.objects.get(productID=product_id,userID=user_id)

如果发现投票,则不更新产品其他更新total_votes上的total_votes。

请注意,如果没有找到符合条件的行,Vote.objects.get将引发一个DoesNotExist异常。

try:
    vote = Vote.objects.get(productID=product_id,userID=user_id)
except Vote.DoesNotExist:
    vote = None
if vote is not None:
    product = get_object_or_404(Product,pk=product_id)
    product.votes_total += 1
    product.save()
    return redirect('/products/' + str(product.id))

答案 1 :(得分:0)

我认为你可以通过在模型的元类中添加unique_together属性来实现。

将views.py更改为以下

class Vote(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    class Meta:
        unique_together = ('product', 'user')


并在views.py

from django.db import IntegrityError
from your_app.models import Vote

@login_required
def upvote(request, product_id):
    if request.method == 'POST':
        product = get_object_or_404(Product, pk=product_id)
        product.votes_total += 1
        # changes
        try:
            Vote.objects.create(product=product, user=request.user)
            product.save()
        except IntegrityError:  # if "unique_together" fails, it will rais an  "IntegrityError" exception
            return HttpResponse("vote not casetd")

        return redirect('/products/' + str(product.id))


注意:更改模型后不要忘记进行迁移;)

答案 2 :(得分:0)

我建议你保持用户和产品之间的多对多关系。像这样:

users = models.ManyToManyField(User)

当用户upvote将该用户添加到产品实例

product.users.add(user)

要得到总投票,你可以这样做:

product.users.count()

即使您多次添加用户,也不会增加计数。

product.users.add(user)
product.users.add(user)
product.users.count()

答案 3 :(得分:0)

只需添加到arp's答案,我就可以将其更改为

try:
    vote = Vote.objects.get(productID=product_id, userID=request.user)
  except Vote.DoesNotExist:
    vote = None

  if vote is None:
    # find product by id and increment 
    product = Product.objects.get(id=product_id)
    vote = Vote(product=product, user=request.user)
    product.votes_total += 1 
    vote.save()
    product.save()

因此更改将是使用request.user查找用户,然后确保创建一个新的Vote实例来连接用户和产品。