Write a simple form
更新poll detail template(polls/detail.html).使得模版包含HTML<form>元素:

上面的模版為每一個問題選擇顯示一個單選按鈕,每個單選按鈕的值是相關(guān)問題選擇的.每個單選按鈕的名稱是"choice".這意味著,當(dāng)某人選擇其中一個單選按鈕并提交表單時(shí),它將發(fā)送POST data choice= #.#是所選的ID,這是html表單的基本概念。
表單的動作設(shè)置為{% url 'polls:vote' question.id %},方法為post.使用post方法非常重要,因?yàn)樘峤槐韱蔚男袨閷⒏淖償?shù)據(jù)服務(wù)器端。當(dāng)要創(chuàng)建一個改變數(shù)據(jù)服務(wù)器端的表單時(shí),使用post方法。
forloop計(jì)數(shù)器統(tǒng)計(jì)了for標(biāo)記循環(huán)的次數(shù)。
因?yàn)槲覀儎?chuàng)建了一個post表單,它可以修改數(shù)據(jù)。所以我們需要擔(dān)心跨站點(diǎn)請求偽造。Django提供了一個非常容易使用的系統(tǒng)來防止這種情況的發(fā)生。簡而言之,所有針對內(nèi)部url的post表單都應(yīng)使用{% csrf_token %}模版標(biāo)記。
現(xiàn)在我們創(chuàng)建一個Django視圖來處理提交的數(shù)據(jù)。我們?yōu)榘@一行的poll應(yīng)用程序創(chuàng)建了一個URLconf。

我們還創(chuàng)建了vote()函數(shù)的虛擬實(shí)現(xiàn)。接下來創(chuàng)建一個真實(shí)的版本,將以下內(nèi)容加到poll/view.py中。

request.POST是一個類似于字典的對象,可以通過鍵名訪問提交的數(shù)據(jù)。在這種情況下,POST['choice']以字符串的形式返回所選選項(xiàng)的ID。
在增加選擇數(shù)后,代碼返回一個HttpResponseRedirect,而不是普通的HttpResponse.HttpResponseRedirect直接受一個參數(shù):用戶將被重定向到的URL。
在成功處理POST數(shù)據(jù)之后,應(yīng)該總是返回一個HttpResponseRedirect.
在本例中,我們在HttpResponseRedirect構(gòu)造函數(shù)中使用reverse()函數(shù)。此函數(shù)有助于在視圖函數(shù)中硬編碼URL。它給出了我們想要傳遞控件的視圖的名稱以及指向該視圖的URL模式的可變部分。在本例中,使用教程3中設(shè)置的URLco f,這個reverse()調(diào)用將返回一個字符串。

3是question.id的值。重定向的URL將會調(diào)用results 視圖來展示最后一頁。
在某人對某個問題進(jìn)行投票之后,vote()視圖將重定向到該問題的結(jié)果頁面。

這和課程3中detail()視圖幾乎是相同的。唯一不同的是模版名稱。
現(xiàn)在創(chuàng)建polls/results.html模版:

現(xiàn)在在瀏覽器中訪問/polls/1頁面,對問題投票。可以看到每次投票后,results page都會更新。如果提交表單時(shí)沒有選擇,將會看到報(bào)錯。
Use generic views: Less code is better
這些視圖代表了web開發(fā)的一些常見情況。根據(jù)URL中傳遞的參數(shù)從數(shù)據(jù)庫中獲取數(shù)據(jù),加載模版,并返回呈現(xiàn)的模版。因?yàn)檫@很常見,Django提供通用視圖系統(tǒng)。
泛型視圖抽象公告模式,以至于不需要編寫python代碼來編寫應(yīng)用程序。
讓我們把poll應(yīng)用程序轉(zhuǎn)換為通用視圖系統(tǒng),這樣我們就可以刪除一些自己的代碼。只需采取以下步驟轉(zhuǎn)換:
1.URLconf轉(zhuǎn)換
2.刪除一些舊的,不需要的視圖
3.基于Django通用視圖引入新的視圖。
Amend URLconf
首先,在polls/urls.py中修改URLconf如下:

注意:第二個和第三個模式路徑字符串中匹配的模式名稱已經(jīng)從<question_id>更改為<pk>。
Amend views

我們用了兩個通用視圖:ListView 和Detail View.這兩個視圖分別抽象了“顯示對象列表”和“顯示特定類型對象的詳細(xì)頁面"的概念。
每個泛型視圖都需要知道它將作用于哪個model.這是由model屬性提供的
DetailView通用視圖期望從URL中捕獲的主鍵值叫pk,所以在通用視圖中把question_id改為pk.
默認(rèn)情況下,DetailView通用視圖使用<app name>/<model name>_detail.html 模版。在本例中,使用的是“polls/question_detail.html".template_name的屬性用來告訴Django 用了指定的模版名稱而不是自動生成的默認(rèn)模版名稱。同時(shí)也給result 視圖指定特定的模版。這用來保證result視圖和detail視圖被渲染為不同的外觀。盡管它們都是Detail View渲染的不同場景。
同樣的,ListView通用視圖使用了默認(rèn)的模版<app name>/<model name>_list.html.我們使用template_name 來告訴ListView 去使用已經(jīng)存在的“polls/index.html”模版。
在之前的課程中,模版提供了包含question 和latest_question_list 上下文變量。DetailView的Question變量是自動提供的。由于我們使用了Django model(Question).Django可以為上下文變量提供確定適當(dāng)?shù)拿Q。然而,對ListView,自動生成的上下文變量是question_list.為了覆蓋它,我們提供了context_object_name屬性,指明我們想用latest_question_list替代。作為一種替代方法,你可以更改模版來匹配新的默認(rèn)上下文變量。