簡體   English   中英

Django - 用戶只能投票一次

[英]Django - User should only able to vote once

我希望用戶只能為類別請求投票一次,但不知何故我收到以下錯誤,我不知道此時如何“正確”調用實例:

無法分配“1”:“CategoryRequests_Voter.voted”必須是“CategoryRequests”實例。

模型.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()

視圖.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)

提前致謝

您需要將voted參數修復為僅category_request ,而不是其主鍵,例如:

CategoryRequests_Voter.objects.create(voter=request.user, voted=category_request)

但是,您可以改進模型和視圖以提高一致性和優雅度。 為了防止User投票兩次或更多次,您可以通過使用unique_together約束來防止為同一個voter創建兩次CategoryRequest_Voter對象並voted

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()

計算給定category_requestCategoryRequests_Voter的數量。

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM