上一篇已经完成了polls的基本功能,接下来完善剩下的vote功能和并使用generic views改进请求处理view。包含表单的简单运用和先后台参数传递。html
编辑detail.html,添加投票投票功能web
<h1>{{question.question_text}}</h1> {% if error_message %}<p><strong>{{ error_message}} </strong></p> {% endif %} <form action="{%url 'polls:vote' question.id %}" method="POST"> {% csrf_token %} {% for choice in question.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>
编辑views.py添加投票功能,注意引入相关的类django
def vote(request, question_id): question = get_object_or_404(Question, pk=question_id) try: selected_choice = question.choice_set.get(pk=request.POST['choice']) except (KeyError, Choice.DoesNotExist): return render(request, 'polls/detail.html', { 'question': question, 'error_message':"you did`t select choice.", }) else: selected_choice.votes += 1 selected_choice.save() return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
request.POST['choice']从post请求里面获取前台传递过来的参数,request.POST 是一个dictionary,键是参数名,值是参数值,档案若是是get请求的话就是request.GET
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))在投票成功以后将页面进行了重定向,防止用户使用浏览器的回退功能以后重复提交表单
到如今为止功能已经完成了,能够进行测试了,启动服务器而后测试相关功能
对于不少web app来讲,须要展现内容的方式相近,好比:查看某个列表,查看某一个的具体内容等等,为此Django提供了generic views——Django诠释了什么是快速便捷开发!浏览器
使用generic views改写views.py服务器
from django.shortcuts import render, get_object_or_404 from django.http import HttpResponse, Http404, HttpResponseRedirect from models import Question, Choice from django.views import generic from django.core.urlresolvers import reverse # Create your views here. class IndexView(generic.ListView): template_name = 'polls/index.html' context_object_name = 'latest_question_list' def get_queryset(self): return Question.objects.order_by('-publ_date')[:5] class DetailView(generic.DetailView): model = Question template_name = 'polls/detail.html' class ResultsView(generic.DetailView): model = Question template_name = 'polls/results.html' def vote(request, question_id): question = get_object_or_404(Question, pk=question_id) try: selected_choice = question.choice_set.get(pk=request.POST['choice']) except (KeyError, Choice.DoesNotExist): return render(request, 'polls/detail.html', { 'question': question, 'error_message':"you did`t select choice.", }) else: selected_choice.votes += 1 selected_choice.save() return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
咱们将index,detail,result都改写了,使用到了ListView和DetailView。app
IndexView复写了get_quesryset方法来实现咱们本身的逻辑,设置了模板页面和返回的参数名称oop
DetailView设置了展现详细信息所须要的model和模板页面post
既然使用了generic views就须要改写urls.py测试
from django.conf.urls import url from . import views app_name = 'polls' urlpatterns = [ url(r'^$', views.IndexView.as_view(), name = 'index'), url(r'^(?P<pk>[0-9]+)/detail/$', views.DetailView.as_view(), name = 'detail'), url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name = 'results'), url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name = 'vote'), ]
为了使用generic views把参数名称改成pk,由于在DetailView里面已经使用了该名称——这就是约定优于配置。url
整个程序基本写完了,咱们回过头来发现,咱们本身真正写了的代码真很少,基本都是依赖Django完成的。可见使用Django快速建站仍是有道理的。
完整代码