Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django TypeError at /polls/1/vote/ _reverse_with_prefix() argument after * must be an iterable, not int

This is the polls app tutorial from the Django Docs.

When I go to the first question http://127.0.0.1:8000/polls/1/, select an option and click 'Vote', I get the error message.

error message

views.py:

from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic

from .models import Choice, Question


class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        """Return the last five published questions."""
        return Question.objects.order_by('-pub_date')[:5]


class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'


class ResultsView(generic.DetailView):
    model = Question
    template_name = 'polls/results.html'


def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        # request.POST['choice'] returns ID of the selected choice as a string
        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()
        # Always return a HttpResponseRedirect after successfully dealing with POST data.
        # This prevents the data from being posted twice if a user hits the Back button.
        return HttpResponseRedirect(reverse('polls:results', args=question_id, ))

polls/urls.py:

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

polls/templates/polls/index.html:

{% if latest_question_list %}
    <ul>
        {% for question in latest_question_list %}
            <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
        {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

polls/templates/polls/detail.html:

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

polls/templates/polls/results.html:

<h1>{{ question.question_text }}</h1>

<ul>
    {% for choice in question.choice_set.all %}
        <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
    {% endfor %}
</ul>

<a href="{% url 'polls:detail' question.id %}">Vote again?</a>

Can anyone please help?

like image 706
ImRajdeepB Avatar asked Sep 18 '25 17:09

ImRajdeepB


1 Answers

The problem is that you write:

    return HttpResponseRedirect(reverse('polls:results', args=question_id, ))

Now args is used for positional arguments, and there can be (in theory) multiple. So it should be a collection of items. For example:

    return HttpResponseRedirect(reverse('polls:results', args=[question_id], ))

Note: in the tutorial they write args=(question_id,). Now that is something different than args=question_id. In Python a (0, ) is not an integer, but a 1-tuple containing one element: 0. In short: the brackets matter.

But there is no need to do all this wrapping. Django has a shorcut redirect(…) [Django-doc], to build HttpResponseRedirects in a more convenient way:

    return redirect('polls:results', question_id)

This takes *args and **kwargs itself as positional and named arguments. So you can write it as if you were calling the view directly as function (with the name of the view in front).

like image 173
Willem Van Onsem Avatar answered Sep 20 '25 07:09

Willem Van Onsem