zoukankan      html  css  js  c++  java
  • django 官方教程翻译-part4

    写一个简单的表单
    更新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>

    解释一下上面的代码:
    1 上面代码为poll对象的每个choice对应一个单选按钮,每个单选按钮的value就是choice的id号,name为choice,也就是说,按下提交按钮,发送的POST数据是这样的choice=3.
    2 设置表单的action为{% url 'polls:vote' poll.id %},method为post.如果需要传递数据的话建议使用post方法.

    3 forloop.counter 是for循环计数器

    4 这里使用了POST表单,存在跨站点请求伪造的安全问题.值得庆幸的是,不需要你为此担心,django自带一个简单易用的拦截系统,那就是,所有的POST表单都应该使用{% csrf_token %}模板标签.现在,创建一个django试图可以处理这个提交上去的数据.

    还记得在polls/urls.py中,这条语句吗?

    url(r'^(?P<poll_id>d+)/vote/$', views.vote, name='vote'),


    现在创建一个真正的投票功能试图vote(),编辑polls/views.py,代码:

    from django.shortcuts import get_object_or_404, render
    from django.http import HttpResponseRedirect, HttpResponse
    from django.core.urlresolvers import reverse
    from polls.models import Choice, Poll
    # ...
    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):
      # Redisplay the poll voting form.
      return render(request, 'polls/detail.html', {
        'poll': p,
        'error_message': "You didn'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,)))

    以上代码包含一些内容在之前没有提到过的:
    1 request.POST是一个类似与字典的对象,可以通过键名访问到提交的数据,在这里request.POST['choice']返回被选择的choice的id.

    注意:django同样也提供了获取get方法提交的数据的request.GET.

    2 如果使用的键名不存在,会抛出KeyError的异常,上面的代码已经对这种异常进行处理了:重定向到提交数据的页面,同时显示错误信息.

    3 增加相应choice的votes值之后,保存.并返回一个HttpResponseRedirect,而不是HttpResponse,这样会把显示页面重定向到第一个参数指定的url那里.

    4 使用POST提交数据成功之后,都应该使用HttpResponseRedirect,这是web最佳实践,不仅仅适用于django.为什么?自己比较一下两者之间的不同吧

    5 在HttpResponseRedirect中使用了reverse,这个函数避免的使用url硬编码,允许想模板中那样使用想polls:results这样的url表示方式.reverse返回的字符串类似这样的形式:
    '/polls/3/results/'
    这个3是p.id的值,这个请求url,会调用results视图来显示最终的页面.
    更多关于HttpRequest对象的内容,阅读:https://docs.djangoproject.com/en/1.6/ref/request-response/

    现在编辑results视图,代码:

    from django.shortcuts import get_object_or_404, render
    
    def results(request, poll_id):
      poll = get_object_or_404(Poll, pk=poll_id)
      return render(request, 'polls/results.html', {'poll': poll})

    以上代码几乎与detail视图,一模一样,稍后会解决这个冗余问题
    现在,编辑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>

    现在访问/polls/1/,然后投票,你会看到每次投票results结果都要更新.如果你不选任何一个choice,然后提交,会看到错误信息.

    使用通用模板,减少代码冗余
    上面创建的detail(),results(),index()都是那么的相似.这些视图都是根据请求url从数据库中获取数据,然后加载一个模板,然后渲染之后的模板.因此django提供了"generic views"(下面称"通用视图")系统来简化模板的开发.减少代码冗余.

    通用视图对通用模式进行抽象,所以你甚至不需要编写一行代码也可以创建一个app.

    现在在poll应用中使用通用视图系统,这个就可以把重复的代码去掉了.使用步骤:
    1 转换URLconf
    2 删除旧的,不必要的视图
    3 新的视图使用通用视图
    为什么要梳理代码:
    通常你在创建一个django app时,会分析通用视图是否能够可以解决你的问题.然后从一开始就使用它,而不是中途重构代码时才引入.本系列教程先是关注如何创建一个app,现在开始注重编程的核心概念.也就是说,你需要有基本的数学基础,才能使用一个计算器.

    修改URLconf
    编辑polls/urls.py,代码:

    from django.conf.urls import patterns, url
    
    from polls import views
    
    urlpatterns = patterns('',
      url(r'^$', views.IndexView.as_view(), name='index'),
      url(r'^(?P<pk>d+)/$', views.DetailView.as_view(), name='detail'),
      url(r'^(?P<pk>d+)/results/$', views.ResultsView.as_view(), name='results'),
      url(r'^(?P<poll_id>d+)/vote/$', views.vote, name='vote'),
    )

    修改视图
    接下来,移除旧的index,detail,results视图,使用django的通用视图代替.编辑polls/views.py,代码:

    from django.shortcuts import get_object_or_404, render
    from django.http import HttpResponseRedirect
    from django.core.urlresolvers import reverse
    from django.views import generic
    
    from polls.models import Choice, Poll
    
    class IndexView(generic.ListView):
      template_name = 'polls/index.html'
      context_object_name = 'latest_poll_list'
    
      def get_queryset(self):
      """Return the last five published polls."""
        return Poll.objects.order_by('-pub_date')[:5]
    
    
    class DetailView(generic.DetailView):
      model = Poll
      template_name = 'polls/detail.html'
    
    
    class ResultsView(generic.DetailView):
      model = Poll
      template_name = 'polls/results.html'
    
    def vote(request, poll_id):
    ....

    上面的代码使用了两个通用视图:ListView和DetailView,这两个视图的含义分别是显示对象列表和显示具体的对象.
    每个通用视图都需要知道它将对哪个模型进行操作.
    DetailView通用视图期望从URL中获取名为"pk"的主键值,因此我们将poll_id变成pk。
    默认情况下,DetailView使用的模板命名规则为<app name>/<model name>_detail.html.它对应这里的模板名为“polls/poll_detail.html"。template_name属性是用于告诉django使用指定的模板名,而不是自动生成的默认模板名。在这里也指定了results list view的模板名——确保它们按照自定义的方式渲染视图。
    同样的,ListView通用视图,使用默认的模板名规则<app name>/<model name>_list.html.这里使用了template name属性指定了一个模板名“polls/index.html”
    在前面的教程中,模板已经提供了包含poll,latest_poll_list上下文变量的上下文。对于DetailView,poll变量是自动提供的-因为正在使用Poll django 模型,而Django能够为上下文变量定义合适的名称。然而,对于ListView,自动生成的上下文变量叫“poll_list”。不过可以通过给context_object_name属性赋值为你想要使用的名字“latest_poll_list”,另外一种解决方案就是把模板中的latest_poll_list改成poll_list,但是第一种方法更加简单和方便。
    运行服务器,使用经过通用视图重构过的poll app。
    通用视图的更多细节,阅读:https://docs.djangoproject.com/en/1.6/topics/class-based-views/

  • 相关阅读:
    pyQt5新手教程 (二)开始你的旅程-编写
    未来写作
    电脑使用问题
    cad学习问题
    chm制作
    github学习之路
    python解决实际问题
    英语学习
    经济学
    通过playgrounds程序学习swift语言及思想
  • 原文地址:https://www.cnblogs.com/chuan-joker/p/django_tutorials_4.html
Copyright © 2011-2022 走看看