位置:
1.找到自己專案用的解釋器存盤位置
H:\pythonProject\Lib\site-packages\django\views\generic\base.py
在base.py里有一個View類
2.也可以通過from django.views import View 按住ctrl點擊View會直接跳到該類的位置
CBV形式的路由
path(r'^login/',views.MyLogin.as_view())
CBV形式的視圖函式
from django.views import View
class MyLogin(View):
def get(self,request): #get請求時執行的函式
return render(request,'form.html')
def post(self,request): #post請求時執行的函式
return HttpResponse('post方法')
CBV原始碼分析:
當上述的login請求來了之后---》會執行后面的views.MyLogin.as_view()---》這個地方應該放的是函式的記憶體地址,views.MyLogin.as_view()執行完,是個函式記憶體地址,---views.MyLogin.as_view()會去views.py中找到MyLogin這個類,然后找as_view()方法,發現沒有--》去其父類中找就是View類中找---》執行as_view()方法最侄訓傳的是一個View類內部的一個view函式記憶體地址---》然后django框架會自動給view這個函式加括號呼叫,再傳入request這個引數--->而view這個內部函式回傳的是return handler(request, *args, **kwargs)就是對應類中get或者post方法
as_view()方法分析:
@classonlymethod # 1.這個as_view是一個類方法,所以用類呼叫時,會自動把呼叫的類傳入給這個函式的cls
def as_view(cls, **initkwargs):
"""Main entry point for a request-response process."""
# 2.因為url那邊沒有傳參,所以initkwargs為空,先忽略該層代碼
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)
)
# 3.執行該view函式
def view(request, *args, **kwargs): # request是當次請求的資料
# 5.cls是當前呼叫的類MyLogin,cls加括號產生物件給了self,這里現在self就是類MyLogin產生的物件
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__
)
# 6.view函式回傳了self.dispatch(request, *args, **kwargs)方法,
# self本身沒有dispatch方法,就去MyLogin中找,MyLogin沒有就去View類中找,找到了
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs
# __name__ and __qualname__ are intentionally left unchanged as
# view_class should be used to robustly determine the name of the view
# instead.
view.__doc__ = cls.__doc__
view.__module__ = cls.__module__
view.__annotations__ = cls.dispatch.__annotations__
# Copy possible attributes set by decorators, e.g. @csrf_exempt, from
# the dispatch method.
view.__dict__.update(cls.dispatch.__dict__)
# Mark the callback if the view class is async.
if cls.view_is_async:
view._is_coroutine = asyncio.coroutines._is_coroutine
# 4.as_view回傳的是該函式內部的view函式記憶體地址,所以具體讀下view函式就行
return view
上述as_view()方法回傳了一個dispatch方法,dispatch方法分析:
# 1.dispatch將MyLogin這個類產生的物件self和request請求物件傳入了dispatch
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.
# 2.判斷request.method方法在不在http_method_names里,ttp_method_names物件里沒有最后去View類里找到了
if request.method.lower() in self.http_method_names:
# 3.通過getattr方法反射,self.http_method_not_allowed這個就當沒有前面的方法時的一個默認值
# handler最后得到的就是MyLogin中定義的get或者post方法的記憶體地址
handler = getattr(
self, request.method.lower(), self.http_method_not_allowed
)
else:
handler = self.http_method_not_allowed
# 4.最后這個方法將handler加括號,再傳入request引數呼叫的結果回傳出去==執行了MyLogin的get或者post方法
return handler(request, *args, **kwargs)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/519024.html
標籤:Python
上一篇:淺談PHP設計模式的工廠模式
