frist Django app — 4、 完善View

上一篇已經完成了polls的基本功能,接下來完善剩下的vote功能和並使用generic views改進請求處理view。包含表單的簡單運用和先後臺參數傳遞。html

目錄

  • vote:完善投票功能
  • generic views:改進views.py

vote

編輯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>
  • 添加了form表單,使用post提交,提交到的地址是polls:vote表明一個地址,好比:http://127.0.0.1:8000/polls/4/vote/.
  • 這裏涉及到了表單提交,添加{% csrf_token %}防止csrf攻擊,原理就是每次使用的token不一致,致使沒法進行僞造請求,從而防止。
  • forloop.counter是for循環的計數器。

編輯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,)))在投票成功以後將頁面進行了重定向,防止用戶使用瀏覽器的回退功能以後重複提交表單

到如今爲止功能已經完成了,能夠進行測試了,啓動服務器而後測試相關功能

generic views

對於不少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快速建站仍是有道理的。

 


完整代碼

http://pan.baidu.com/s/1o8zqGhs

相關文章
相關標籤/搜索