CBV源码分析流程
urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
...
path('test/',views.Test.as_view()), # path里面放了一个view的内存地址
]
看下 as_views方法
@classonlymethod
def as_view(cls, **initkwargs): #类方法,类调用自动将类作为参数传入,cls=Test
...
# 闭包函数
def view(request, *args, **kwargs): # 内层函数
self = cls(**initkwargs) # 实例化一个对象
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get # 判断对象有没有的get方法
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs)
# 一切皆对象,给对象赋值属性
view.view_class = cls # 将类名赋值给view的view_class属性
view.view_initkwargs = initkwargs
return view # 返回内层函数的内存地址
# 流程
在路由匹配阶段:views.Test.as_view()
(1)Test类调用类方法as_view:自动将Test作为参数传入
(2)as_view()是一个嵌套函数,它返回了内层函数的内存地址
(3)view()闭包函数,引用外部的cls,返回的是self.dispatch(request,*args,**kwargs)
再看下self.dispatch()
self是一个Book对象,调用方法的查找顺序,先找自己的,没有去父类中找,再没有去父类的父类中找
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
def dispatch(self, request, *args, **kwargs):
# request是当次请求的request self是Book类的实例化对象
if request.method.lower() in self.http_method_names: #判断request,method的小写是否在http_method_names中
handler = getattr(self, request.method.lower(), self.http_method_not_allowed) # 反射 hander是Book类get方法的内存地址
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) # 执行get(request,*args,**kwargs)
原生的request对象
http请求经过WSGI服务器会被拆分成一个env大字典,env大字典会包含http请求的所有数据。django框架会将env大字典中的数据封装给原生的request对象。而DRF框架中的request对象是对原生request的二次封装
扩展点:
# python中一切皆对象
class Beast(object):
def __init__(self, name):
self.name = name
def hello(self):
print(f'hello,{self.name}')
Beast.method = 'get'
print(Beast.method) # get