Reputation: 721
I'm creating this django app using the tutorial and i'm up to part 4 https://docs.djangoproject.com/en/dev/intro/tutorial04/
The app display a basic poll and when you click on it , it display some choices and a button to vote.
The problem is when I click on vote . It display Page not found. I think the problem is the redirection but I don't know where to pin point the problem. The first page is the index.html which display the questions then it's the detail.html which display the choices and question. I know when I click on vote , it goes back to the app URLconf then the urlconf execute the view function and the view function execute the results.
My detail.html are
<h1>{{ poll.question }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="/myapp/{{ poll.id }}/vote/" method="post">
{% csrf_token %}
{% for choice in poll.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>
My urls.py inside myapp are :
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
from django.conf.urls import patterns, include, url
urlpatterns = patterns('myapp.views',
url(r'^$', 'index'),
url(r'^(?P<poll_id>\d+)/$', 'detail'),
url(r'^(?P<poll_id>\d+)/results/$', 'results'),
url(r'^(?P<poll_id>\d+)/vote/$', 'vote'),
)
My views.py are :
from django.http import HttpResponse
from myapp.models import Poll ,choice
from django.template import Context, loader
from django.http import Http404
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
def index(request):
latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
return render_to_response('myapp/index.html', {'latest_poll_list': latest_poll_list})
def results(request, poll_id):
p = get_object_or_404(Poll, pk=poll_id)
return render_to_response('myapp/results.html', {'poll': p})
def vote(request, poll_id):
p = get_object_or_404(Poll, pk=poll_id)
try:
selected_choice = p.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the poll voting form.
return render_to_response('myapp/detail.html', {
'poll': p,
'error_message': "You didn't select a choice.",
}, context_instance=RequestContext(request))
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('myapp.views.results', args=(p.id,)))
def detail(request, poll_id):
p = get_object_or_404(Poll, pk=poll_id)
return render_to_response('myapp/detail.html', {'poll': p},
context_instance=RequestContext(request))
My results.html are:
<h1>{{ poll.question }}</h1>
<ul>
{% for choice in poll.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
<a href="/myapp/{{ poll.id }}/">Vote again?</a>
Thank you for helping me . This will be my first breakthrough app if I can get this to work.
My Main URLconf is :
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^polls/', include('myapp.urls')),
url(r'^admin/', include(admin.site.urls)),
)
Upvotes: 3
Views: 1916
Reputation: 13328
Loose the myapp bit of the form action.
It should be
<form action="polls/{{poll.id}}/vote" method="post">
This matches the regex in your urls.py file -
url(r'^polls/', include('myapp.urls')),
and then in myapp.urls -
url(r'^(?P<poll_id>\d+)/vote/$', 'vote'),
The include
function means that django is trying to match ^polls/(?P<poll_id>\d+)/vote/$
If you look at the error page your getting you can see the url's that django's trying to match against (none of them contain 'myapp' it should be polls).
IMPORTANT
When you get further on in the tutorial you'll see that you shouldn't be hardcoding urls in your templates (as jpic rightly points out). At this stage you need to swap out the form action for {% url 'polls:vote' poll.id %}
.
Upvotes: 2
Reputation: 33420
You should not hardcode a URL anywhere - just like for file system paths. You're not only killing kittens but also making your code less solid !
Read about reversing urls for starters, and using named urls for main dish, and about {% url %} templatetag for dessert.
At the time of digestive, you will be a master of Django url system B)
In the tutorial you linked, they don't hardcode urls:
{% url 'polls:vote' poll.id %}
That's the way to go !!
Make sure you don't have a hardcoded url anywhere in your templates and your problem will go away.
Upvotes: 6