Django中的CBV
阿新 • • 發佈:2019-12-31
CBV模式的介面
CBV模式即為API式的寫法,一個資源類接受一系列的請求。本文討論的是View的直接子類中的概念和方法,Django REST framework中重寫和添加了大量的方法,可以直接繼承自XXXAPIView,不再本文的討論範圍。
- 首先在試圖函式中建立View的子類
- 在類中定義請求方式的類方法
- 在urlpatterns中新增方式不同,需要加as_view()
- 需要加(),呼叫這個方法
class HelloView(View):
def get(self,request):
return HttpResponse("GET view ok")
複製程式碼
View中的方法
- __init__
- as_view
- dispaych
- http_method_not_allowed
- options
- __allowed_methods
- http_method_name
呼叫順序為
as_view
- as_view
- as_view傳入的引數不能和請求方法同名
def get(self,request):
return HttpResponse("GET %s" % self.msg)
複製程式碼
- as_view傳遞進來的引數必須是類中既有的屬性
- 定義view函式
- 建立自己的物件
def as_view(resquest):
def view(cls)
self = cls(**initkwargs)
複製程式碼
- 記錄傳入的引數HelloView
- 只要支援get請求就支援head請求
- 在view函式中呼叫了dispatch
dispatch
- 根據請求方法名字小寫取既有請求方法列表中判定
def dispatch(self,request,*args,**kwargs):
if request.method.lower() in self.http_method_names:
handler = getattr(self,request.method.lower(),self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request,**kwargs)
複製程式碼
- 如果請求不存在直接返回http_method_not_allowed
- 如果存在,會根據請求方法獲取對應的屬性
- 屬性不存在也返回http_method_not_allowed
- 屬性存在返回正常屬性
- 呼叫屬性
http_method_not_allowed
- 直接返回HttpResponse
_allowed_methods
- 用列表迭代器,返回請求方法的名字
return [m.upper() for m in self.http_method_names if hasattr(self,m)]
複製程式碼
options
- 是一個請求方法
- 預設所有的CBV都支援options方法
類試圖CBV流程
as_view
通過內建方法dispatch來分發請求方法
重寫View父類,實現繼承自重寫類的類,可以支援請求方法
class HelloCustomView(object):
@classmethod
def as_view(cls):
def view(request):
self = cls()
return self.dispatch(request)
return view
def dispatch(self,request):
handler = getattr(self,None)
if not handler:
return HttpResponse("request method not allowed")
return handler(request)
def get(self,request):
return HttpResponse("GET")
def post(self,request):
return HttpResponse("POST")
def put(self,resquest):
return HttpResponse("PUT")
複製程式碼
TemplateView
繼承關係如圖
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-gSkf4aVq-1573007279134)(github.com/belingud/im…)]
有三個父類
- TemplateResponseMixin
- ContextMixin
- View
- 用來分發請求的父類
TemplateResponseMixin
- 屬性
- template_name
- template_engine
- response_class
- content_type
- 方法
- render_to_respose
- 將傳入的上下文渲染形成響應
- get_template_names
- render_to_respose
- 作用
- 用來渲染模板的多繼承類
ContextMixin
- 屬性
- 方法
- get_context_data
- 作用
- 一個將傳入的鍵值對轉化為'view'鍵字典的預設多繼承父類
View
- 屬性
- http_method_names
- 方法
- as_view
- view
- dispatch
- http_method_not_allowed
- options
- as_view
- 作用
- 用來分發請求
TemplateView實現的功能:
- 分發請求:dispatch方法
- 實現了get請求:在TemplateView類中的get方法
- 獲取上下文:ContextMixin多繼承父類
- 渲染成響應:TemplateResponseMixin中的render_to_respose方法
ListView
繼承關係如圖
[外鏈圖片轉存失敗,建議將圖片儲存下來直接上傳(img-BIF0IjzQ-1573007279135)(github.com/belingud/im…)]
ListView只是繼承父類,沒有在其中增改方法
有兩個父類:
- MultipleObjectTemplateResponseMixin
- BaseListView
MultipleObjectTemplateResponseMixin的屬性和方法
屬性:
- template_name_suffix = '_list'
方法:
- def get_template_names(self):返回模板名字的列表
BaseListView的屬性和方法
無屬性
方法:
- get():將傳入的上下文渲染成響應,預設支援get請求
return self.render_to_response(context)
複製程式碼
MultipleObjectTemplateResponseMixin
有一個父類
TemplateResponseMixin
也是View的父類,屬性和方法同上文的TemplateResponseMixin
BaseListView
有兩個父類
- MultipleObjectMixin
他有一個父類ContextMixin,父類的類方法 get_context_data
將傳入的鍵值對轉化為’view’鍵字典的預設多繼承父類
屬性:
- allow_empty
- context_object_name
- model
- ordering
- 以某個欄位排序,可以制定多個
- page_kwargs
- paginate_by
- paginate_class
- paginate_orphans
- queryset
傳入一個model或者query_set,返回modelname_list,否則預設為object_list
model = Book # 或下面的query_set
queryset = Book.objects.all()
複製程式碼
方法:
- get_queryset
- get_ordering
- paginate_queryset
- get_paginate_by
- get_paginator
- get_paginate_orphans
- 返回最後一個頁碼
- get_allow_empty
- get_context_object_name
- get_context_data
- 用來重寫
即上文中的View
流程概覽
graph LR
A[url] --> B[as_views]
B[as_views]-->C[dis_patch]
C[dis_patch]-->D[get]
D[get]-->E[get_queryset]
E[get_queryset]-->F[get_context_data]
F[get_context_data]-->G[render_to_response]
複製程式碼
graph TD
A[get_queryset]-->B[queryset屬性和model屬性]
A[get_queryset]-->C[get_ordering]
A[get_queryset]-->D[get_allow_empty]
複製程式碼
graph TD
A[get_context_data]-->B[get_paginate_by]
A[get_context_data]-->C[get_context_object_name]
A[get_context_data]-->D[向context中注入資料]
複製程式碼