django 類視圖解析 -FormView

django 類視圖可以幫我們輕松處理特定功能的邏輯端朵,django 基本類視圖分為四類:

本文解析編輯類視圖的 FormView。后續(xù)會繼續(xù)對其他類視圖進(jìn)行解析幽告。

實現(xiàn)的功能

FormView 是 Django 為表單處理提供的類視圖宽菜,該類視圖解決以下三種路徑的表單請求:

  1. 初始GET(空或者預(yù)填充表單)
  2. 具有無效數(shù)據(jù)的POST(通常重新顯示帶有錯誤的表單)
  3. 具有有效數(shù)據(jù)的POST(處理數(shù)據(jù)并通常重定向)

其中葵姥,頁面的GET請求將實現(xiàn)初始GET紊浩;用戶提交請求后旭等,根據(jù)用戶提交的數(shù)據(jù)是否通過驗證酌呆,分別實現(xiàn)具有有效數(shù)據(jù)的POST和無效數(shù)據(jù)的POST。

視圖如何實現(xiàn)功能的搔耕?

FormView通過下圖所示邏輯解決上述三中路徑的請求隙袁。

FormView實現(xiàn)的邏輯

圖中:
1 通過dispatch()方法實現(xiàn);
2 通過get_form() 方法實現(xiàn)弃榨;
3 通過form.is_valid() 方法實現(xiàn)菩收;
4 通過form_valid() 方法實現(xiàn);
6 通過get_form()方法實現(xiàn)鲸睛,
7 通過render_to_response()方法實現(xiàn)娜饵。

它們的組合可以實現(xiàn)FormView的功能:

  • 初始GET:通過圖中1-5-6-7路徑實現(xiàn);
  • 具有無效數(shù)據(jù)的POST:通過圖中1-2-3-5-7路徑實現(xiàn)官辈;
  • 具有有效數(shù)據(jù)的POST:通過圖中1-2-3-4路徑實現(xiàn)箱舞。

從圖中我們可以看到,2钧萍、6都是通過get_form() 方法實現(xiàn)form的實例化褐缠,它們的區(qū)別在于:

  • 2中的form實例化對應(yīng)的是POST請求,它將生成含有初始數(shù)據(jù)风瘦、POST方法中獲取到的數(shù)據(jù)的表單實例(如果初始數(shù)據(jù)與POST方法中數(shù)據(jù)的關(guān)鍵詞相同队魏,表單綁定的是POST中的數(shù)據(jù));
  • 6中的form實例化對應(yīng)的是GET請求,它將生成具備初始數(shù)據(jù)的表單實例胡桨;

實現(xiàn)上述流程官帘,F(xiàn)ormView需要設(shè)置以下兩個屬性(方法):

  • form_class : 表單類,用于 get_form() 方法昧谊,這里使用 ApplicationForm 刽虹;該屬性也可以通過重寫 get_form_class() 方法進(jìn)行定義;
  • success_url:表單驗證成功后跳轉(zhuǎn)到的url呢诬,用于 form_valid() 方法涌哲。該屬性也可以通過重寫 get_success_url() 方法進(jìn)行定義。

如果需要設(shè)置表單的初始值尚镰,可以設(shè)置一下屬性:

  • initial:字典阀圾,key為表單字段名,用于get_form()方法狗唉,該屬性也可以通過重寫get_initial() 方法進(jìn)行定義初烘。

代碼是如何實現(xiàn)上述功能的

GET請求

get() 方法來處理 GET請求,F(xiàn)ormView內(nèi)置的get() 方法為:

def get(self, request, *args, **kwargs):
    """
    Handles GET requests and instantiates a blank version of the form.
    """
    return self.render_to_response(self.get_context_data())

該方法與實現(xiàn)了圖1中5-6-7路徑分俯,其中肾筐,5-6通過self.get_context_data()實現(xiàn),7通過self.render_to_response()實現(xiàn)缸剪。

get_contecxt_data() 方法具體內(nèi)容為:

def get_context_data(self, **kwargs):
    """
    Insert the form into the context dict.
    """
    if 'form' not in kwargs:
        kwargs['form'] = self.get_form()
    return super(FormMixin, self).get_context_data(**kwargs)

如果 get_context_data() 的參數(shù)中沒有 form 吗铐,這里將使用 form_class 設(shè)置的表單類創(chuàng)建 form實例作為關(guān)鍵詞參數(shù) ‘form’ 的值,django 內(nèi)部會將所有的關(guān)鍵詞參數(shù) 傳入響應(yīng)的 context 中橄登,因此抓歼,我們可以在 HTML 中通過 {{ form }}來訪問表單實例讥此。

POST請求

post() 方法來處理 POST請求拢锹,F(xiàn)ormView內(nèi)置的post() 方法為:

def post(self, request, *args, **kwargs):
    """
    Handles POST requests, instantiating a form instance with the passed
    POST variables and then checked for validity.
    """
    form = self.get_form()
    if form.is_valid():
        return self.form_valid(form)
    else:
        return self.form_invalid(form)

該方法實現(xiàn)了圖中1-2-3-5-7路徑和1-2-3-4路徑。其中:

? 2 通過form = self.get_form()實現(xiàn)萄喳;

? 3 通過form.is_valid()實現(xiàn)卒稳;

? 5-7 通過 self.form_invalid(form) 實現(xiàn);

? 4 通過self.form_valid(form)實現(xiàn)他巨。

self.form_invalid(form)

處理沒有通過驗證的表單充坑。它的代碼是:

def form_invalid(self, form):
    """
    If the form is invalid, re-render the context data with the
    data-filled form and errors.
    """
    return self.render_to_response(self.get_context_data(form=form))

它與 GET請求中 get() 方法實現(xiàn)的功能類似,唯一的區(qū)別在于:它將未通過驗證的表單實例 傳入self.get_context_data() 方法中染突,這樣 context中的form為驗證未通過的表單實例捻爷,而不是 get() 中的空的表單實例。

self.form_valid(form)

處理通過驗證的表單份企,它的代碼是:

def form_valid(self, form):
    """
    If the form is valid, redirect to the supplied URL.
    """
    return HttpResponseRedirect(self.get_success_url())

它只實現(xiàn)了一項功能:跳轉(zhuǎn)到成功頁面也榄。

這里采用的是HttpResponseRedirect類進(jìn)行處理,HttpResponseRedirect 實現(xiàn) HTTP 302。簡單來說甜紫,它將向定義的跳轉(zhuǎn)成功頁面 發(fā)起 GET請求降宅。

HTTP 302

RFC1945,也就是HTTP1.0在介紹302時說囚霸,如果客戶端發(fā)出POST請求后腰根,收到服務(wù)端的302狀態(tài)碼,那么不能自動的向新的URI發(fā)送重復(fù)請求拓型,必須跟用戶確認(rèn)是否該重發(fā)额嘿,因為第二次POST時,環(huán)境可能已經(jīng)發(fā)生變化(嗯劣挫,POST方法不是冪等的)岩睁,POST操作會不符合用戶預(yù)期。但是揣云,很多瀏覽器(user agent我描述為瀏覽器以方便介紹)在這種情況下都會把POST請求變?yōu)镚ET請求捕儒。

? RFC2616,也就是HTTP1.1在介紹302時說邓夕,如果客戶端發(fā)出非GET刘莹、HEAD請求后,收到服務(wù)端的302狀態(tài)碼焚刚,那么就不能自動的向新URI發(fā)送重復(fù)請求点弯,除非得到用戶的確認(rèn)。但是矿咕,很多瀏覽器都把302當(dāng)作303處理了(注意岸啡,303是HTTP1.1才加進(jìn)來的术陶,其實從HTTP1.0進(jìn)化到HTTP1.1,瀏覽器什么都沒動),它們獲取到HTTP響應(yīng)報文頭部的Location字段信息境氢,并發(fā)起一個GET請求社裆。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末翁授,一起剝皮案震驚了整個濱河市残拐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瑞侮,老刑警劉巖的圆,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異半火,居然都是意外死亡越妈,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門钮糖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來梅掠,“玉大人,你說我怎么就攤上這事∪块埽” “怎么了赂韵?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長挠蛉。 經(jīng)常有香客問我祭示,道長,這世上最難降的妖魔是什么谴古? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任质涛,我火速辦了婚禮,結(jié)果婚禮上掰担,老公的妹妹穿的比我還像新娘汇陆。我一直安慰自己,他們只是感情好带饱,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布毡代。 她就那樣靜靜地躺著,像睡著了一般勺疼。 火紅的嫁衣襯著肌膚如雪教寂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天执庐,我揣著相機與錄音酪耕,去河邊找鬼。 笑死轨淌,一個胖子當(dāng)著我的面吹牛迂烁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播递鹉,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼盟步,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了梳虽?” 一聲冷哼從身側(cè)響起址芯,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎窜觉,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體北专,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡禀挫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拓颓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片语婴。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砰左,到底是詐尸還是另有隱情匿醒,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布缠导,位于F島的核電站廉羔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏僻造。R本人自食惡果不足惜憋他,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望髓削。 院中可真熱鬧竹挡,春花似錦、人聲如沸立膛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宝泵。三九已至耸序,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鲁猩,已是汗流浹背坎怪。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留廓握,地道東北人搅窿。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像隙券,于是被迫代替她去往敵國和親男应。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 在上一個章節(jié)娱仔,我們已經(jīng)創(chuàng)建了一個基礎(chǔ)的Blog程序°迤現(xiàn)在我們將使用一些Dajngo高級功能,去實現(xiàn)一個完整的blo...
    金金剛狼閱讀 3,586評論 1 12
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理牲迫,服務(wù)發(fā)現(xiàn)耐朴,斷路器,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • HTML表單 在HTML中盹憎,表單是 ... 之間元素的集合筛峭,它們允許訪問者輸入文本、選擇選項陪每、操作對象等等影晓,然后將...
    蘭山小亭閱讀 3,418評論 2 14
  • 基于類的視圖 Django中的視圖是一個可調(diào)用對象镰吵,它接收一個請求然后返回一個響應(yīng)。這個可調(diào)用對象不僅僅限于函數(shù)挂签,...
    蘭山小亭閱讀 4,577評論 1 13
  • 22年12月更新:個人網(wǎng)站關(guān)停疤祭,如果仍舊對舊教程有興趣參考 Github 的markdown內(nèi)容[https://...
    tangyefei閱讀 35,183評論 22 257