Reputation: 29
I've been doing the django tutorial and I'm now trying to adapt it to my needs. In part 04, the turorial teaches us how to write forms.
I have re-used this part of the tutorial to try and write a radio-button select form.
Most of it is working as the different inputs are shown, selectable, and validating does send me to the associated page.
The code is supposed to display an error_message if the form is validated without an answer. My problem is that this message is already displayed the first time I open the page.
I've looked for the reason everywhere but I seem to be the only one having this problem.
Here is the index.html file
<!DOCTYPE html>
<html>
<head>
<title>Syl - Projects</title>
</head>
<h1>Project List</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="" method="post">
{% csrf_token %}
{% for choice in project_list %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.name }}</label><br />
{% endfor %}
<input type="submit" value="Accéder au projet" />
</form>
</html>
And here is the views.py file
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.template import RequestContext, loader
from django.core.urlresolvers import reverse
from gantt.models import Project
from gantt.models import *
def index(request):
project_list = Project.objects.order_by('name')
try:
selected_project = project_list.get(pk=request.POST['choice'])
except (KeyError, Project.DoesNotExist):
return render(request, 'gantt/index.html', {
'project_list': project_list,
'error_message': "Vous n'avez pas fait de choix.",
})
else:
return HttpResponseRedirect(reverse('syl:project', args=(selected_project.slug,)))
... ...
Fixed thanks to your answers.
I had to add an IF condition to prevent the call to request.post on the first page load. Adding this however, meant I had to add another render for the initial page load since it wasn't possible to use the Redirect for that purpose (its arguments didnt exist yet).
Thansk again.
New version of the views.py file :
def index(request):
project_list = Project.objects.order_by('name')
if request.method=="POST":
try:
selected_project = project_list.get(pk=request.POST['choice'])
except (KeyError, Project.DoesNotExist):
return render(request, 'gantt/index.html', {
'project_list': project_list,
'error_message': "Vous n'avez pas fait de choix.",
})
else:
return HttpResponseRedirect(reverse('syl:project', args=(selected_project.slug,)))
else:
return render(request, 'gantt/index.html', {'project_list': project_list})
Upvotes: 2
Views: 1666
Reputation: 3755
Try adding an "If request.method == 'POST'" before you try to get your selected project in the view. When this view is loaded with a GET request by someone viewing the page for the first time, your code is already looking for a POSTed variable to use. It isn't there yet, so you get the error on load.
Wrapping that part in such an if block will tell your code "if there is no submission yet, just display the form. If there is a submission, process it." Right now it tries to skip to processing right away, sees that no selection has been made, and throws the error.
Upvotes: 1