supersheep1
supersheep1

Reputation: 721

How do I combat this django error Page not found (404)

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.enter image description here

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

enter image description here

Upvotes: 3

Views: 1916

Answers (2)

Aidan Ewen
Aidan Ewen

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

jpic
jpic

Reputation: 33420

Don't hardcode urls

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 !

Reverse urls instaed !

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)

Read the tutorial

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

Related Questions