django 学习笔记(四)

四、Writing your first Django app, part 4

写一个简单的表单

继续Part 3的例子

1.修改 polls/detail.html 模版文件,增加form元素

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

注意事项:

  • 增加一些 radio 按钮,按钮的value是choice.id的值,提交的时候通过post中的choice值来处理
  • 使用 method=“post” 方法
  • 提交的地址是 {% url 'polls:vote' poll.id %}
  • forloop.counter 是循环计数变量
  • 使用 {% csrf_token %} 避免跨站攻击

2.增加处理post数据的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,)))

代码解读:

  • 使用 request.POST['choice'] 的方法访问 POST 数据
  • 如果在字典访问中找不到 choice key,抛出 KeyError 异常
  • 尽量使用HttpResponseRedirect 代替 HttpResponse
  • 通过使用 reverse()方法来避免在视图中写入硬编码的网址

3.完善结果显示的页面 results()

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

4.建立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>

使用通用视图来改写上面的例子

  • ListView
  • DetailView

1. 在urls.py中的设置

url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),

2. 视图中的写法

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):
    ....

3.解读

  • pk作为主键 url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
  • model 表的名称
  • template_name 模版的名称
  • context_object_name 自定义模版中的变量名称

你可能感兴趣的:(django 学习笔记(四))