我希望用户只能对类别请求进行一次投票,但是不知何故我收到了以下错误,并且我不知道该如何“正确地”调用实例:
无法分配“ 1”:“ CategoryRequests_Voter.voted”必须为 “ CategoryRequests”实例。
models.py
# Category Requests Model
class CategoryRequests(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
....
# Vote(s) of Category Requests Model
class CategoryRequests_Voter(models.Model):
voter = models.ForeignKey(User, on_delete=models.CASCADE)
voted = models.ForeignKey(CategoryRequests, on_delete=models.CASCADE)
published_date = models.DateField(auto_now_add=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
views.py
def category_request_up_vote (request, pk):
category_request = get_object_or_404(CategoryRequests, pk=pk)
if request.method == 'GET':
if CategoryRequests_Voter.objects.filter(voter=request.user, voted=category_request.pk).exists():
messages.error(request, 'You already voted for this request.')
else:
category_request.up_vote = F('up_vote') + 1
category_request.save()
CategoryRequests_Voter.objects.create(voter=request.user, voted=category_request.pk)
messages.success(request, 'You have successfully Provided an Up-Vote for this Request')
return redirect('category_request_detail', pk=category_request.pk)
else:
messages.error(request, 'Uuups, something went wrong, please try again.')
return redirect('category_request_detail', pk=category_request.pk)
预先感谢
答案 0 :(得分:1)
您需要将voted
参数固定为category_request
,而不是其主键,例如:
CategoryRequests_Voter.objects.create(voter=request.user, voted=category_request)
但是,您可以改进模型和视图以提高一致性和美观性。为了防止User
进行两次或两次以上的投票,可以防止为相同 CategoryRequest_Voter
和voter
创建两次创建voted
对象的过程,通过使用unique_together
约束:
class CategoryRequests_Voter(models.Model):
voter = models.ForeignKey(User, on_delete=models.CASCADE)
voted = models.ForeignKey(CategoryRequests, on_delete=models.CASCADE)
published_date = models.DateField(auto_now_add=True, null=True)
class Meta:
unique_together = ('voter', 'voted')
def publish(self):
self.published_date = timezone.now()
self.save()
此外,我们可以使用get_or_create
并因此仅从数据库中进行一次读取。通常,更改数据的视图应使用POST请求(而不是GET)来执行此操作。 GET请求不应有副作用。
def category_request_up_vote (request, pk):
category_request = get_object_or_404(CategoryRequests, pk=pk)
if request.method == 'POST':
__, created = CategoryRequests_Voter.objects.get_or_create(
voter=request.user,
voted=category_request
)
if created:
category_request.up_vote = F('up_vote') + 1
category_request.save()
messages.success(request, 'You have successfully Provided an Up-Vote for this Request')
else:
messages.error(request, 'You already voted for this request.')
else:
messages.error(request, 'Uuups, something went wrong, please try again.')
return redirect('category_request_detail', pk=category_request.pk)
也许值得计算CategoryRequest_Voter
的数量,而不是增加投票数,因为例如由于删除User
或票数,最终可能会投票数不再与该CategoryRequests_Voter
对象的CategoryRequests
数一致。
也许计数对象的数量并不是有效的每次投票,但是您可以使任务不时地运行,从而计算:
CategoryRequests_Voter.objects.filter(voted=category_request).count()
计算给定CategoryRequests_Voter
的{{1}}的数量。
答案 1 :(得分:0)
def category_request_up_vote (request, pk):
category_request = get_object_or_404(CategoryRequests, pk=pk)
try:
if request.method == 'GET':
if CategoryRequests_Voter.objects.filter(voter=request.user, voted=category_request).exists():
messages.error(request, 'You already voted for this request.')
return redirect('category_request_detail', pk=category_request.pk)
else:
category_request.up_vote = F('up_vote') + 1
category_request.save()
CategoryRequests_Voter.objects.create(voter=request.user, voted=category_request)
messages.success(request, 'You have successfully Provided an Up-Vote for this Request')
return redirect('category_request_detail', pk=category_request.pk)
else:
messages.error(request, 'Uuups, something went wrong, please try again.')
return redirect('category_request_detail', pk=category_request.pk)
except:
messages.error(request, 'Uuups, something went wrong, please try again.')
return redirect('category_request_detail', pk=category_request.pk)