你可能會好奇為什么在這里我們又要介紹CBV開發模式, 在前面的文章中, 我們呼叫視圖函式都是使用 FBV 開發模式, 用的好好的為什么又要換呢? 其實不然,這是一個循序漸進的程序, 就像編程基礎 和 框架開發, 我們都要學, 只不過是順序的不同而已,
在這篇文章中, 我們要介紹關于 CBV開發模式 與 FBV 開發模式的區別, 以及他們各種的優點和使用場所, 最后我們一起閱讀 Views 的原始碼理解一下 CBV模式下的請求是如何分發的,非常的神奇.
工具: pycharm 2020
《django 從入門到 放棄 》第十篇
沙漏在下雨
記錄學習中的一點一滴......
文章目錄
- FBV 開發模式:
- CBV 開發模式:
- CBV中類屬性設定方法
FBV 開發模式:
- FBV開發模式 全名為:
function based views, 是一種基于函式的視圖呼叫,他的優點就是簡單上手,不需要去繼承函式, 所以我們也不需要去閱讀很多底層代碼,缺點就是不符合python的面向物件的思想, 也就是不可以去繼承和多型, - 我們之前 用的基本都是 FBV開發模式, 這里我們給出一個例子.
在urls.py 中
#urls.py
from django.urls import path
from app01 import views
urlpatterns = [
path('login.html', views.login, name="login"),
]
在views.py中
from django.shortcuts import HttpResponse
from django.shortcuts import render
def login(request):
if request.method == "GET":
return render(request, "xxx.html", locals())
else:
return HttpResponse("ok")
以上, 就是一個簡易的 FBV 開發模式, 其實我們在 urls.py 檔案中, django也給了我們注釋 :
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
那下面我們講一講CBV開發模式:
CBV 開發模式:
- CBV開發模式, 全稱為
class based views是一種基于類的視圖函式呼叫,符合python的面向物件思想, 可以完好的繼承和多型, CBV開發模式將各種方式用函式分開,實作了功能的分離, 比如可以直接使用 get(), post() 之類的方法, 同時省去了我們用 if 進行邏輯的判斷, 提高了代碼的可讀性, 但是也有弊端, 如果我們的代碼不是很規范,或者繼承的類過于多的時候,CBV開發模式這個時候,就不是一個很好的選擇,而選擇FBV開發模式, 這二種模式,都可以用, 一般用CBV開發模式用的更多一點, 這個看個人習慣吧, 下面我們舉例看一看 CBV開發模式的呼叫方式.
在 urls.py 檔案下;
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
我們可以看到這樣的一個提示, 這是呼叫的方法, 基于類的使用, 所以我們也需要在views.py 里面創建一個類函式,
# urls.py
from django.urls import path
from app01 import views
urlpatterns = [
path('', views.Home.as_views(), name="home"),
]
然后在 views.py 檔案下
from django.views import View
class Home(View): #需要繼承自View類
def get(self,request):
return HttpResponse("ok")
def post(self,request):
pass
使用這個方式我們需要繼承一個類
from django.views import View 我們創建的類,就必須繼承這個類, 不然就無法實作邏輯分發的功能, 那這個CBV開發模式是怎么實作的呢? 我們閱讀一下原始碼.

進入 Views 這個類, 第一個就可以看到 http_method_names , 這是一個串列,里面包括各種請求的方式, Views類里面封裝了這些方法, 可以讓我們直接使用 get(), post() … 之類的方法就直接呼叫, 省去了if判斷, 那繼續往下看,
接下來 我們看 as_views() 方法, 因為我們在配置路由的時候,呼叫了這個方法,
def as_view(cls, **initkwargs):
"""Main entry point for a request-response process."""
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError(
'The method name %s is not accepted as a keyword argument '
'to %s().' % (key, cls.__name__)
)
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key))
def view(request, *args, **kwargs):
self = cls(**initkwargs)
self.setup(request, *args, **kwargs)
if not hasattr(self, 'request'):
raise AttributeError(
"%s instance has no 'request' attribute. Did you override "
"setup() and forget to call super()?" % cls.__name__
)
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs
# take name and docstring from class
update_wrapper(view, cls, updated=())
# and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
return view
- 閱讀原始碼我們可以知道, 前面在 for 回圈 里面進行了一些例外的判斷和拋出, 然后就是 def views() 函式, 之后,呼叫了 update_wrapper() ,這個方法, 通過繼續觀察, 還是其關鍵作用的還是下面的 update_wrapper(view, cls.dispatch, assigned=()) 這個方法, 引數中將 view, cls.dispatch, 其實都是這個類的方法, 我們找到 dispach() 方法,
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
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, *args, **kwargs)
dispatch 中文就是調度,分發的意思, 而且在這個原始碼中, 也給了提示, 就是調度,拋開這些, 我們閱讀原始碼,
-
如果我們的方法名小寫 在 這個 self.http_method_names: 里面, 也就是在規定的方法里面, 那么就去取這個方法名的函式, 最后回傳給 Handler,進行下面的操作, 最后實作了 請求的分發, 否則就會拋出錯誤例外,
-
如果還剛興趣, 可以進入 Handler 原始碼里面進行閱讀, 我這里只是拋磚引玉.
CBV中類屬性設定方法
類屬性的設定方法有兩種,一種可以是使用 Python 方法,即繼承父類,重寫其相應的屬性,或者添加新的屬性,第二種方式我們可以使用路由中的 as_view() 方法傳遞引數屬性值,從而來指定類的屬性,示例如下所示
#第一種方式重寫父類
class Home(View): #需要繼承自View類
username='me'
def get(self,request):
return HttpResponse("ox")
def post(self,request):
pass
class LoginViewChild(LoginView):
#繼承后重寫類屬性
username = 'me'
#第二種方法也可以
urlpatterns = [
path(r'Home/', Home.as_view(username="me"))
]
在這篇文章中, 我們要介紹關于 CBV開發模式 與 FBV 開發模式的區別, 以及他們各種的優點和使用場所, 最后我們一起閱讀 Views 的原始碼理解一下 CBV模式下的請求是如何分發的,非常的神奇.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/229978.html
標籤:python
