[PYTHON] DJango Note: From the beginning (form processing)

Tutorial 4. We have finally entered the final tutorial. We will finish a voting application called polls.

Template using form

Describe the template of the detail page as follows.

detail.html ######

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

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="/polls/{{ 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 }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>

It contains some words that you see for the first time.

You can imagine this by name, but it's a value defined on the views.py side, so you don't have to remember it separately.

A cliché that means the number of times a loop has been turned. It's easy to remember because it's just the meaning.

So-called CSRF measures. This seems to be the most important. If you want to send a POST method to your site, you should consider it mandatory. So what is CSRF? So I googled. http://e-words.jp/w/CSRF.html For convenience of using this, views.py will also be edited.

views.py ####

from django.template import RequestContext	#RequestContext seems to be a subclass of Context
# ...
def detail(request, poll_id):
    pobject = get_object_or_404(Poll, pk=poll_id)	#pk is an abbreviation for Primary Key. Reserved word?
    return render_to_response('polls/detail.html', {'poll': pobject},
                               context_instance=RequestContext(request))	# context_A new instance has been added. Maybe reserved words

Also implement the vote part.

from django.shortcuts import get_object_or_404, render_to_response
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.template import RequestContext
from polls.models import Choice, Poll
#...
def vote(request, poll_id):
    pobject = get_object_or_404(Poll, pk=poll_id)
    try:
        selected_choice = pobject.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        return render_to_response('polls/detail.html', {
            'poll': pobject,
            'error_message': "First choose the option",
        }, context_instance=RequestContext(request))
    else:
        selected_choice.votes += 1
        selected_choice.save()
        return HttpResponseRedirect(reverse('polls.views.results', args=(pobject.id,)))

Here are some words I haven't seen before, so I'll summarize them.

Received the data that has been POSTed. You can retrieve the value according to the name by doing request.POST ['name']. I feel that it is written as $ _POST in any language.

A subclass of Context. You have to put the HttpRequest object in the first argument here. Here, the first argument request of the view function vote is entered as it is (the accessed HttpRequest is probably automatically assigned to the first argument of the view function).

The name (probably fixed) to use when returning render_to_response with a shortcut. Assign an HttpRequest object.

render_to_response('for/your/template',{'name':value},context_instance)

Do you feel that you specify the template in the first argument, put the data in the second argument, and pass the data to the template in the request of the third argument?

Update the set database. Here, the value of selected_choice.votes (data name defined in models.py) is incremented by one and then overwritten.

I'm not sure from that alone, so if you dig a little deeper, This selected_choice seems to refer to the data with the POSTed'choice'value as the Primary Key from the choice_set. So, this choice_set is a set of choices obtained from pobject (the way to write hoge_set seems to be a cliché. For details, see Tutorial 1 in tutorial01.html)). Reviewing the template, the value of the "choice" radio button is "{{choice.id}}", and what is this id?

python manage.py sql polls

Can be confirmed at

"id" integer NOT NULL PRIMARY KEY

The data looks like this (id seems to be automatically generated even if it is not defined in models.py). Well, in short, it's like what number of choice.

In other words

# def vote….
        selected_choice.votes += 1
        selected_choice.save()

In the part of, the data with the value of the selected choice as id is added and saved. If you check the template, this id will be the value of the radio button as it is, and as a result, the data of the item selected by the radio button will be updated.

I'm surprised that it's been so long, but that's probably the process flow (please tell me if it's different).

In previous programs, it was HttpResponse exclusively, but here Redirect is attached. In the first argument reverse, the contents are

’/polls/[id]/results/‘

It is converted and returned as. Specify the redirect destination? args seems to be an argument to bring to the redirect destination (can it be put in poll_id of the results function?). There's only one content here, but don't forget to add a comma! It seems to be the rule of the Web to redirect when POST is successful.

So, next, we will design the redirect destination results.

def results(request, poll_id):
    pobject = get_object_or_404(Poll, pk=poll_id)
    return render_to_response('polls/results.html', {'poll': pobject})

Also make a template.

results.html ######

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

<ul>
{% for choice in poll.choice_set.all %}
    <li>{{ choice.choice }} -- {{ choice.votes }}Vote</li>
{% endfor %}
</ul>

<a href="/polls/{{ poll.id }}/">Do you still vote?</a>

The above is the summary of the tutorial. However, in this case, I often use shortcuts. That wouldn't be a learning experience, so I rewrote it to one that doesn't use shortcuts.

views.py ######

from polls.models import Poll,Choice
from django.http import HttpResponse,HttpResponseRedirect
from django.template import Context,loader,RequestContext
from django.core.urlresolvers import reverse
from django.http import Http404

def index(req):
	latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
	temp = loader.get_template('polls/index.html')
	contxt = Context({
			  'latest_poll_list':latest_poll_list
	})
	return HttpResponse(temp.render(contxt))

def detail(req,poll_id):
	try:
		pobject = Poll.objects.get(pk=poll_id)
	except Poll.DoesNotExist:
		raise Http404
	temp = loader.get_template('polls/detail.html')
	contxt = RequestContext(req,{
			  'poll':pobject
	})
	return HttpResponse(temp.render(contxt))

def results(req,poll_id):
	try:
		pobject = Poll.objects.get(pk=poll_id)
	except Poll.DoesNotExist:
		raise Http404
	temp = loader.get_template('polls/results.html')
	contxt = Context({
		'poll':pobject
	})
	return HttpResponse( temp.render(contxt) )

def vote(req,poll_id):
	try:
		pobject = Poll.objects.get(pk=poll_id)
	except Poll.DoesNotExist:
		raise Http404
	
	try:
		selected_choice = pobject.choice_set.get(pk=req.POST['choice'])
	except (KeyError,Choice.DoesNotExist):
		temp = loader.get_template('polls/detail.html')
		contxt = RequestContext(req,{
			'poll':pobject,
			'error_message':"You have to select choice!"
		})
		return HttpResponse(temp.render(contxt))
	else:
		selected_choice.votes += 1
		selected_choice.save()
		return HttpResponseRedirect( reverse('polls.views.results',args=(pobject.id,) ) )

Ichiou operation is also confirmed.

What I struggled with was where to put the context_instance, which is included as the third argument in the render_to_response of detail and vote. Solved by writing RequestContext (request, {'name': value}).

Even so, I wrote the same thing many times and it's not cool. I've managed to understand the flow, and maybe it's time to use the shortcut.

Next time I will use the generic view.

Recommended Posts

DJango Note: From the beginning (form processing)
DJango Note: From the beginning (using a generic view)
DJango Note: From the beginning (creating a view from a template)
DJango Memo: From the beginning (preparation)
Get the value from the [Django] Form
DJango Note: From the beginning (simplification and splitting of URLConf)
DJango Memo: From the beginning (model settings)
Get only the text from the Django form.
DJango Memo: From the beginning (creating a view)
DJango Memo: From the beginning (Error screen settings)
DJango Memo: From the beginning (more edits to the management screen)
Django note 4
Django Note 5
DJango memo: From the beginning (using the management screen) my addictive point
Django Note 1
Django note 3
Django note 2
Learning notes from the beginning of Python 1
Omit BOM from the beginning of the string
Learning notes from the beginning of Python 2
DJango memo: From the beginning (editing the management screen) There is a mystery
Django Contact Form 2
[Django] Create a form that automatically fills in the address from the zip code
Finding the beginning of Abenomics from NT magnification 2
Django Suggested Form
Django Form Gleaning
Django contact form
The wall of changing the Django service from Python 2.7 to Python 3
Learn Nim with Python (from the beginning of the year).
Study from the beginning of Python Hour1: Hello World
Mathematical understanding of principal component analysis from the beginning
Set the form DateField to type = date in Django
[2020 version] Scraping and processing the text from Aozora Bunko
Study from the beginning of Python Hour8: Using packages
[Django] Give Form a dynamic initial value from Model
The beginning of cif2cell
[Note] Beginning of programming
Django Girls Tutorial Note
The story of a Django model field disappearing from a class
Points to note when deleting multiple elements from the List
How to do the initial setup from Django project creation