Django官方文档学习笔记:Tutorial: Part 4

Django官方文档学习笔记:Tutorial: Part 4

    继续折腾这个投票应用,本章主要讲如何处理表单。   

    一、写一个表单
    修改原来的detail.html模板(" polls/ templates/polls/detail.html "):
< 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 >
    forloop.counter         for循环的次数
    {% csrf_token %}    避免别的网站伪造post请求数据。

    如代码所描述的,post之后会跳到vote去,修改poll应用的views.py(" polls/views.py")实现一下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    根据key访问post提交的数据。同理get请求则使用request.GET
    request.POST['choice']    如果post数据中没有choice,会爆出KeyError异常。
    HttpResponseRedirect    页面重定向。避免post多次。
    reverse()    调用url链接,避免硬编码。

    创建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 >

< href ="{% url 'polls:detail' poll.id %}" > Vote again? </ a >

    二、使用通用视图:减少代码
    在web开发中,从数据库查询,并渲染模板页面到显示,这是个很常见的情况。Django提供了一个用来快速生成视图的“generic views”系统。可以将通用的ListView、DetailView的渲染通过它在URLconf中完成。
    修改URLconf
    修改poll应用的urls配置文件(" polls/urls.py"):
from  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 ' ),
)
   
    修改views
    到此,可以把原视图(" polls/views.py")中的index()、detail()、results()方法删掉了。

    这里使用了ListView、DetailView。需要注意的是,DetailView使用“ pk”去匹配url中的id。
    DetailView、ListView默认分别调用“<app_name>/<model_name>_detail.html”、“<app_name>/<model_name>_list.html”模板,可以通过“ template_name”参数指定特定的模板。
    ListView默认生成的传递给模板的上下文变量为“<model_name>_list”,可通过“ context_object_name”参数来指定传输变量。
   

你可能感兴趣的:(Django官方文档学习笔记:Tutorial: Part 4)