djangofor-loopbuttonvote-up-buttons

How to increase a value (pushing a button) in a html django template using a for loop?


I'm actually programming a ask-a-question website for a school project. I followed the first step of the django tutorial from the official website but i'm now trying to improve it myself.

I added a 'vote' button in each div (which are created in a for loop) which i want to increase in my views.vote.

Some code will be more explainful.

So here is my detail.html which shows all my questions and the choices/responses to this question with a vote button for each choice :

{% block content %}
    <h2>{{ question.question_text }}</h2>

    {% 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 %}
            <div class="choices">
                <label for="">{{ choice.choice_text }}</label><br>
                <p>{{ choice.votes }} vote{{ choice.votes|pluralize }}</p>
                <input type="submit" name="vote" id=""  value="Vote">
            </div>
        {% endfor %}
        <br>
    </form>
    <a href="{% url 'polls:choice' question.id %}">Add a choice</a>
{% endblock %}

And here is my views.vote which get the right question and (should) get the right choice's 'votes' value to increase :

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['vote'])
    except (KeyError, Choice.DoesNotExist):
        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:detail', args=(question.id,)))

My 'votes' value is declared in my 'Choice' Object like this :

class Choice(models.Model):
    votes = models.IntegerField(default=0)

Actually, when i push my 'Vote' button, i get this error message :

invalid literal for int() with base 10: 'Vote'

I'm a real beginner in django so, be kind !


Solution

  • Your error is in the line:

    <input type="submit" name="vote" id=""  value="Vote">
    

    Since you are using

    selected_choice = question.choice_set.get(pk=request.POST['vote'])
    

    The request.POST['vote'] will return 'Vote' as a result. It is because it fetches the value of the <input> which is defined as value="Vote" but your view statement requires an integer value.

    To solve your problem, you need to pass the id of the choice in the value field like:

    <input type="submit" name="vote" id=""  value="{{ choice.id }}">
    

    I would recommend you to use button instead of input as:

    <button type="submit" name="vote" id=""  value="{{ choice.id }}">Vote</button>