Django官方文檔學習筆記:Tutorial: Part 4
繼續(xù)折騰這個投票應用,本章主要講如何處理表單。一、寫一個表單
修改原來的detail.html模板("polls/templates/polls/detail.html"):
forloop.counter for循環(huán)的次數(shù)<h1>{{ poll.question }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' poll.id %}" 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>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' poll.id %}" 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>
{% csrf_token %} 避免別的網(wǎng)站偽造post請求數(shù)據(jù)。
如代碼所描述的,post之后會跳到vote去,修改poll應用的views.py("polls/views.py")實現(xiàn)一下vote響應方法。
# Create your views here.
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponse, HttpResponseRedirect
from django.core.urlresolvers import reverse
from polls.models import Poll, Choice
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):
return render(request, 'polls/detail.html', {
'poll': p,
'error_message': "You din't select a choice.",
})
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('polls:results', args=(p.id,)))
request.POST 根據(jù)key訪問post提交的數(shù)據(jù)。同理get請求則使用request.GETfrom django.shortcuts import get_object_or_404, render
from django.http import HttpResponse, HttpResponseRedirect
from django.core.urlresolvers import reverse
from polls.models import Poll, Choice
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):
return render(request, 'polls/detail.html', {
'poll': p,
'error_message': "You din't select a choice.",
})
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('polls:results', args=(p.id,)))
request.POST['choice'] 如果post數(shù)據(jù)中沒有choice,會爆出KeyError異常。
HttpResponseRedirect 頁面重定向。避免post多次。
reverse() 調(diào)用url鏈接,避免硬編碼。
創(chuàng)建results模板文件("polls/templates/polls/results.html")。
<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="{% url 'polls:detail' poll.id %}">Vote again?</a>
<ul>
{% for choice in poll.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
<a href="{% url 'polls:detail' poll.id %}">Vote again?</a>
二、使用通用視圖:減少代碼
在web開發(fā)中,從數(shù)據(jù)庫查詢,并渲染模板頁面到顯示,這是個很常見的情況。Django提供了一個用來快速生成視圖的“generic views”系統(tǒng)。可以將通用的ListView、DetailView的渲染通過它在URLconf中完成。
修改URLconf
修改poll應用的urls配置文件("polls/urls.py"):
修改viewsfrom django.conf.urls import patterns, url
from django.views.generic import ListView
from django.views.generic.detail import DetailView
from polls.models import Poll
urlpatterns = patterns('',
# ex: /polls/
url(r'^$', ListView.as_view(queryset=Poll.objects.order_by('-pub_date')[:5],
context_object_name='latest_poll_list',
template_name='polls/index.html'), name='index'),
# ex: /polls/5/
url(r'^(?P<pk>\d+)/$', DetailView.as_view(
model=Poll,
template_name='polls/detail.html'
), name='detail'),
# ex: /polls/5/results/
url(r'^(?P<pk>\d+)/results/$', DetailView.as_view(
model=Poll,
template_name='polls/results.html'
), name='results'),
# ex: /polls/5/vote/
url(r'^(?P<poll_id>\d+)/vote/$', 'polls.views.vote', name='vote'),
)
from django.views.generic import ListView
from django.views.generic.detail import DetailView
from polls.models import Poll
urlpatterns = patterns('',
# ex: /polls/
url(r'^$', ListView.as_view(queryset=Poll.objects.order_by('-pub_date')[:5],
context_object_name='latest_poll_list',
template_name='polls/index.html'), name='index'),
# ex: /polls/5/
url(r'^(?P<pk>\d+)/$', DetailView.as_view(
model=Poll,
template_name='polls/detail.html'
), name='detail'),
# ex: /polls/5/results/
url(r'^(?P<pk>\d+)/results/$', DetailView.as_view(
model=Poll,
template_name='polls/results.html'
), name='results'),
# ex: /polls/5/vote/
url(r'^(?P<poll_id>\d+)/vote/$', 'polls.views.vote', name='vote'),
)
到此,可以把原視圖("polls/views.py")中的index()、detail()、results()方法刪掉了。
這里使用了ListView、DetailView。需要注意的是,DetailView使用“pk”去匹配url中的id。
DetailView、ListView默認分別調(diào)用“<app_name>/<model_name>_detail.html”、“<app_name>/<model_name>_list.html”模板,可以通過“template_name”參數(shù)指定特定的模板。
ListView默認生成的傳遞給模板的上下文變量為“<model_name>_list”,可通過“context_object_name”參數(shù)來指定傳輸變量。
posted on 2013-05-10 15:36 此號已被刪 閱讀(667) 評論(0) 編輯 收藏 所屬分類: Python