Ceres
Ceres

Reputation: 2658

I want users to vote only once and for only one option for my polling app I made with django

I am new to django, and wanted to improve the polls tutorial app. this is the exact code from the tuttorial but this allows users to vote again for the same or different option if they want to, I want to restrict users to only one vote and choice per question.

Views
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 (KeyError, Choice.DoesNotExist):
        # Redisplay the question voting form.
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
        #shows results
Models
from django.db import models
import datetime
from django.utils import timezone
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')



class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
Template for vote
<h1>{{ question.question_text }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
<input type="submit" value="Vote">
</form>

Upvotes: 0

Views: 707

Answers (1)

Arjun Shahi
Arjun Shahi

Reputation: 7330

For this you might want to create another new model called Vote which will store choice and user who voted on this choice

 class Vote(models.Model):

    choice = models.ForeignKey(Choice,on_delete=models.CASCADE)
    voter = models.ForeignKey(User,on_delete=models.CASCADE)

Now you can check whether the user already voted on this choice or not like this:

def vote(request, pk):
   choice = get_object_or_404(Choice, pk=pk)
   if Vote.objects.filter(choice=choice,voter=request.user).exists():
      messages.error(request,"Already Voted on this choice")
      return redirect..
   else:
      choice.votes += 1
      choice.save()
      Vote.objects.create(voter=request.user, choice=choice)
      return redirect()

Upvotes: 2

Related Questions