我希望用户只能投票一次。我知道要创建另一个名为“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))
答案 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实例来连接用户和产品。