2017-04-15 74 views
2

我有民意調查清單(問題),並希望檢查某個User是否對該民意調查投了票。這裏是我的模型:檢查用戶是否對某項民意調查投了票

class Question(models.Model): 
    has_answered = models.ManyToManyField(User) 
    question_text = models.CharField(max_length=80) 

    def __str__(self): 
     return self.question_text 

class Choice(models.Model): 
    question = models.ForeignKey(Question, on_delete=models.CASCADE) 
    choice_text = models.CharField(max_length=100) 
    votes = models.IntegerField(default=0) 

    def __str__(self): 
     return self.choice_text 

這是我的看法,當投票表決用戶投票:

def poll_answer(request): 
    if request.method == 'POST': 
     answer = request.POST.get('answer') 
     question = request.POST.get('question') 

     q = Question.objects.get(question_text=question) 

     choice = Choice.objects.get(id=answer) 
     choice.votes += 1 
     choice.save() 
     ... 

我已經在我的Question模式,閱讀文檔後,我認爲這是增加了一個ManyToMany場正確的方式來鏈接在某個問題上投票的用戶名單,但我不確定是否誠實。最終目標是放入我的模板,如下所示:if request.user in question.has_answered: don't display the poll

我該如何去做這件事?

回答

0

首先,有一些邏輯和原理圖問題需要解決。

您基於可能返回多個對象的非唯一字段question_text篩選問題。你應當通過id檢索問題:

q = Question.objects.get(pk=question) 

或使question_text領域獨樹一幟:

question_text = models.CharField(max_length=80, unique=True) 

其次,通過Python一個遞增votes可能導致race conditions可能發生在兩個用戶希望增加同時投票。這就是爲什麼存在F對象在Django,它可以讓你做的增量在數據庫級別:

from django.db.models import F 

def poll_answer(request): 
    ... 
    choice = Choice.objects.get(id=answer) 
    choice.votes = F("votes") + 1 
    choice.save() 
    ... 

我有投票(問題)的列表,並想檢查,如果某個用戶有對該投票進行投票。

通過你的設計,你不能,因爲你沒有存儲誰投這問題。當用戶對問題進行投票時,您只需遞增votes字段。要做到這一點

的一種方式,你可以votes字段更改爲ManyToManyField並開始儲存誰已經把投票選擇用戶:

class Question(models.Model): 
    text = models.CharField(max_length=80, unique=True) 

    def __str__(self): 
     return self.text 

class Choice(models.Model): 
    question = models.ForeignKey(Question) 
    choice = models.CharField(max_length=100) 
    votes = models.ManyToMany(User) 

,所以你可以檢查用戶是否已經參與了投票作爲如下:

has_voted = request.user.choice_set.filter(question=question).exists() 

而且,在我看來,投票行動在這裏可以像QuestionUser模式之間的中間模式,所以你可能想看看how to define extra fields on many-to-many relationships在Django文檔中的一節。

如果我是你的話,我會做類似如下:

class Question(models.Model): 
    text = models.CharField(max_length=80, unique=True) 
    voters = models.ManyToManyField(User, through="Vote") 

class Choice(models.Model): 
    question = models.ForeignKey(Question) 
    text = models.CharField(max_length=100) 

class Vote(models.Model): 
    question = models.ForeignKey(Question, on_delete=models.CASCADE) 
    user = models.ForeignKey(User, on_delete=models.CASCADE) 
    choice = models.ForeignKey(Choice, on_delete=models.CASCADE) 
    voted_at = models.DateTimeField(auto_now_add=True) 
0

有很多方法可以做到這一點, 我寧願創建一個投票另一種模式:

class Vote(models.Model): 
    user = models.ForeignKey(User, unique=True) 

class Choice(models.Model): 
    question = models.ForeignKey(Question, related_name='choices') 
    choice_text = models.CharField(max_length=100) 
    votes = models.ForgeinKey(Vote) 

隨着該模型可以很容易計算的票數: 和你有利益知道究竟用戶投票的問題

Choice.objects.get(pk=PK).votes.count() 

要檢測一個用戶已經投票:

if Vote.objects.filter(question=1, user=user_id).count() == 1 
user_id voted for question 1 already 
0

可以創建一個vote視圖這樣的:

def vote(request, question_id): 
    question = get_object_or_404(Question, pk=question_id) 
    try: 
     selected_choice = question.choice_set.get(pk=request.POST['choice']) 
    except: 
     return render(request, 'your_question_page.html', {'question': question, 
      'error_message': "Please select an option"}) 
    else: 
     selected_choice.votes += 1 
     selected_choice.save() 

     return redirect('polls:result_page_view', question_id=question_id) 

上面vote視圖將提取所選擇的選項的選擇項ID,但如果有像沒有選擇則except塊將執行和打印選項的錯誤給出錯誤消息,否則它將所選選項的投票計數增加1並保存。 希望這可以幫助你。