# 課程鏈接
4天搞定django rest framework源碼和實戰_哔哩哔哩_bilibili
# 課程內容
(1)內容概要_略
(2)內容回顧_略
(3)django 視圖之 CBV 基本使用
(4)django 視圖之 CBV 源碼流程
(5)django 視圖之面試題和 csrf 補充
(6)django 視圖之 CBV 和解決 csrf 認證
(7)以上內容梳理_略
【知識點補充---自己加的】
# 豈曰無衣,與子同袍
# (1)直接上圖
# (2)Django 的 FBV 和 CBV
1)FBV 就是基於函數的視圖, 就跟我們平時使用的一樣。
2)CBV 是基於類的視圖。就是要繼承 django.views 中的 View 。見下圖所示的代碼。當執行了這一個類的時候,前端傳來是什麼請求,類就會自動執行相應的方法。比如 post 請求,那麼類就會執行 post 的方法。
此時路由函數要這麼寫,就是要加 .as_view() 來作為路由函數,這裡是固定的要求,不為什麼。
那麼上面就是一個 CBV 的模式。
# (3)postman 偽造請求
1)我們不可能為每一種請求再去設計相應的表單提交什麼的,這沒意義。我們可以使用 postman 這種工具來偽造各種請求,來查看後端返回的數據。
2)postman 的下載安裝。下載鏈接:Download Postman | Get Started for Free
// 下載完成後,我們直接打開後就會自動安裝了,並且在桌面生成快捷方式。這個時候打開該快捷方式,即如下圖所示。其實 postman 有網頁端,但是需要桌面代理才能測試本地的 url 。
3)postman 簡單使用。如下圖所示,我們點了加號之後的頁面,然後我們也具體的使用了下,測試了 post 請求。這裡的報錯是因為我們沒有關閉 django 中的 csrf 認證。這裡可以直接去 settings.py 文件中的中間件處注釋掉該認證即可。
# (4)列表生成式,直接給我寫的代碼和注釋吧
# (5)面向對象
1)封裝。體現在兩個方面,一個方面是對同一類方法封裝到類中。如下圖所示,就是將各自類的對應自己方法,然後進行封裝。
另外一個是將數據封裝到對象中,就是我們將數據傳入到類裡面,然後裡面的 self.a1 = 傳參 a1,大致就是這個意思,供類的調用,也就是我們實例化這個類後,我們不僅能使用類的方法,還有裡面的數據。
2)簡單聊聊裝飾器 @property,這個裝飾器的作用會在別的數據分析的課裡面細講,我們只需要知道,在定義函數的前面引用。之後我們在調用該函數的時候,就可以不加括號了,就跟調用屬性一樣。見下面的代碼塊,算是一種入門級別的理解吧。
# -*- coding=utf-8 -*- # github: night_walkiner # csdn: 潘迪仔 class Foo: def __init__(self): self.price = 100 # (1) 裝飾器,這裡必須寫在最前面,函數名就是後續調用時候用的, # 而且 @property 裝飾後的函數,必須是返回某個值,然後調用是屬性調用,就是對方法不用加括號 # 這裡必須提一句,如果我們之後要賦值,比如下面的代碼: """ 類 Foo 下的 @property def price(self,value): pass 之後調用的時候,如果我們 Foo.price 會提示少一個參數, 而如果我們這樣 Foo.price(100) ,依然會報錯, 因此我們要使用裝飾器要求的設置,即下面的方式來設置數值什麼的 """ @property def price(self): return print("裝飾器") # 如果今後我們要對 price 進行賦值的話,必須裝飾 price.setter , # 注意觀察啊!!! @price.setter def price(self, value): self.price = value # 這個是一樣的,也是要用(1) 中定義的 price 來 .deleter 作為裝飾器 @price.deleter def price(self): del self.price
那麼來上一個實例看看,就是武 sir 寫的代碼,我就不復現了。這裡是也是封裝實例的擴展,很簡單。如果遇到問題去復現一下,或者研讀下吧,不贅述了。
# (1)內容詳細
1)關於 CBV 開發的結構。事實上 HTTP 請求本質上是發了一堆字符串,通過 /r 進行分隔的。但是我們是怎麼處理請求的呢? Django 源碼中是使用反射來做的,也就是 getattr() 方法來做。如果不使用反射方法,我們就要使用 request.method 去一個個做判斷執行。(基本所有支持 CBV 結構的框架都是使用反射去實現的)
2)對於 CBV 而言,我們使用了這種模式的時候,實際上就是在路由地址,執行了 as_view() 的方法,然後我們可以看 as_view() 的源碼,可以看到不論是執行什麼請求,都要執行 self.dispatch()
3)self.dispatch 的源碼如下,首先將獲取的 request.method 的請求變小寫,比如原來的是 GET 變成 get,然後判斷這個請求是不是在 self.http_method_names 裡面,這個self.http_method_names 裡面存著的是各自請求類型,如 post,put 等等。 getattr(x, "y") 相當於 x.y 的意思,類似屬性調用。
4)CBV 的具體流程
5)父類和子類的方法的執行順序。見下圖所示的代碼:
如下圖所示,比如當前是 post 請求,然後我們執行了 dispatch 方法。
第一: 那麼系統就會從子類中找到 dispatch ,子類又會去父類裡面找父類的 dispatch,但是 self 是代指子類,經過反射後找到的是 post 請求,
第二: 然後再從子類中調用 post 方法,將結果再返回給父類的 dispatch, 父類的 dispatch 再傳回給子類的 dispatch ,然後再返回給用戶。
# (1)CBV 源碼流程的補充。相信這一塊會隨著深入學習而更扎實,且有更好的理解。
# (2) 繼承
# (1)Django 中間件
1)Django 中間件最多只能寫 5 個方法,就是下圖列舉的。以前說的 process_request() 和 process_response() 兩種方法是最常用的而已。
其中 process_exception() 方法是只有異常的時候才會執行,沒有異常就不會執行。對於 process_render_template() 方法,如果視圖函數返回的是 render() 就會執行這個中間件,否則執行 HttpResponse() 的話是永遠不會執行。
2)中間件的執行流程 _(Django 1.10 以上的版本),見下圖所示,我們簡述一下中間件的執行流程,當請求進來的時候:
第一:首先是按序執行所有中間件的 process_request() 方法,然後進行路由匹配,但是不執行視圖函數;
第二:執行完路由匹配後,再返回第一層中間件,繼續按序執行他們的 process_view() 方法,執行完後才開始執行視圖函數;
第三:視圖函數正確執行和返回(HttpResponse)的時候,就開始執行 process_response() 方法返回給浏覽器。
第四:如果說,在執行路由函數時候發生錯誤,那麼就會執行 process_exception() 方法返回異常;
第五:如果說,視圖函數正確執行了,但是返回的是 render() 那麼就執行中間件的process_render_template() 方法,然後返回給浏覽器。
【第四、第五就是下圖見注釋的部分。】
3)使用中間件能做什麼?比較常用的就是權限認證和用戶登錄認證。
# (2)csrf 認證的面試題
1)Django 中的中間件 csrf_token 的實現。csrf 的中間件是寫在了 process_view() 方法裡面的。【見後面的(3)的 3)的講解】
# (3)免除 csrf 認證裝飾器和單獨 csrf 認證的裝飾器
1)假設我們將全局的視圖函數都添加了 csrf 認證,也就是在中間件的地方給 csrf 打開認證了,那麼我們如果想免除某個視圖函數的 csrf 認證就可以使用免除認證的裝飾器了。那麼導入的模塊語句為:from django.views.decorators.csrf import csrf_exempt
如下圖所示,那麼我們在視圖函數 users 前引用了 @csrf_exempt 就是免除該函數的 csrf 認證了。
2)場景二,如果我們注釋了全局的 csrf 認證,又想對某幾個特定的視圖函數加上 csrf 認證,那麼就可以使用單獨的 csrf 裝飾器了。導入模塊的語句為:from django.views.decorators.csrf import csrf_protect 。使用方法是和免除的裝飾器一樣的。如下圖所示。
3)有了上面的基礎,我們就知道為什麼 csrf 的認證需要寫在 process_view() 中了,這是因為在執行認證的時候,需要檢索這個視圖函數是否免除了認證(或者帶有認證),這裡面是需要邏輯判斷的。而如果寫在 process_request() 方法中,請求過程並沒有路由匹配的信息,csrf 都沒找到視圖函數,還談什麼檢查視圖函數是否帶有相應的裝飾器!緊接著,如果需要 csrf 認證,那麼再去檢查是否符合 csrf_token 的規則
# (1)CBV 怎麼自定義 csrf 認證(自定義就是免除還是單獨設置認證)
1)前面我們講的都是基於 FBV 的來講解 csrf 裝飾器的用法的。那麼對於 CBV 要自定義 csrf 認證的話,就不是簡單的在類中的函數上加裝飾器了。【csrf 裝飾器就是 csrf_exempt 或者 csrf_protect】
2)解決方法就是使用 from django.utils.decorators import method_decorator 中的 method_decorator 裝飾器,這可以對 CBV 結構設置自定義 csrf 裝飾器用的。比如第一種方法就是如下的方法,@method_decorator(csrf_exempt) 那麼就是免除這個視圖類的 csrf 認證(對於單獨設置也是一樣的)。其實就是 @method_decorator(csrf 裝飾器),只要是按照如下的格式就行。
class StudentsView(View): # 自定義認證---方法一, 就是放在 dispatch 方法前面。 # 這是官方規定的,沒有為什麼。 @method_decorator(csrf_exempt) def dispatch(self, request, *args, **kwargs): print("before") # super() 不是簡單的繼承當前類的父類,而是執行整個繼承關系 # 也就是說,找方法的時候,先在自己裡面找,找不到采取父類找, # 如果父類再找不到,就去第二繼承類去找 ret = super(StudentsView, self).dispatch(request, *args, **kwargs) # print(ret) print("after") return ret def get(self, request, *args, **kwargs): print("get") return HttpResponse("GET") # @method_decorator(csrf_exempt) 如果是加在這裡是沒用的!!! #(也就是對單獨方法是無效的) # 因為官方規定了,就是要放在 dispatch 方法上面,而且 dispatch 還得放在最前面。 def post(self, request, *args, **kwargs): return HttpResponse("POST") def put(self, request, *args, **kwargs): return HttpResponse("PUT") def delete(self, request, *args, **kwargs): return HttpResponse("DELETE")
3)也可以是下面的方法,就是放在視圖類的最上面,但是編寫的時候就是@method_decorator(csrf 裝飾器,name="dispatch")。具體見下面代碼的注釋。
from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt, csrf_protect # 自定義認證---方法二, name裡面其實就是方法名。簡單說就是找到這個類方法,然後加上這個裝飾器 @method_decorator(csrf_exempt, name="dispatch") class StudentsView(View): def get(self, request, *args, **kwargs): print("get") return HttpResponse("GET") def post(self, request, *args, **kwargs): return HttpResponse("POST") def put(self, request, *args, **kwargs): return HttpResponse("PUT") def delete(self, request, *args, **kwargs): return HttpResponse("DELETE")
# 直接上圖
# (1)getattr() 反射的使用。
還得提一點就是比如 getattr(obj, '_negotiator', None),就是返回 obj._negotiator,如果有的話。我們之前說了,如果沒這個屬性,反射就會報錯,這個時候就可以用後面 None 了,意思是說,如果沒有這個屬性,系統也不報錯,而是會返回一個 None。
# (2)類繼承的優先級