目录
路由绑定
urlpatterns = [ # 1)项目启动,将test函数地址绑定给/test/路由 # 2)请求/test/访问后台,后台就会调用绑定的test函数 url(r'^test/$', views.test), # 1)项目启动,将as_view()函数执行结果返回的view函数地址绑定给/test/路由 # 2)请求/test/访问后台,后台就会调用绑定的view函数 # 3)view函数会将请求交给dispatch方法完成分发,分发(反射)给视图类的不同方法处理请求 url(r'^test/$', views.Test.as_view()), ]
业务处理
fbv 每一个接口都会对应一个函数来响应请求
cbv 可以将一个资源的增删改查所有操放在一个类中管理,在内部再分方法逐一处理
(高内聚低耦合:六个接口和一个类有关,但都能在类内部处理)
三个View其实是同一个类 继承View的目的: i)继承as_view()方法,完成路由的配置 ii)继承dispath()方法,完成请求分发 注:如果自己写as_view()和dispath()方法,自定义视图类可以不用继承任何类的 from django.http import JsonResponse from django.views import View from django.views.generic import View from django.views.generic.base import View class Test(View): def get(self, request, *args, **kwargs): return JsonResponse('cbv ok', safe=False)
django 的类视图拥有自动查找指定方法的功能, 通过调用是通过
as_view()
方法实现urls.py
from meduo_mall.demo import views urlpatterns = [ url(r'register/$', views.Demo.as_view()) ]
views.py
from django.views.generic import View class Demo(View): def get(self, request): return HttpResponse('get page') def post(self, request): return HttpResponse('post page')
为什么
as_view
能自动匹配指定的方法先看源码
@classonlymethod def as_view(cls, **initkwargs): # 实际上是一个闭包 返回 view函数 """ Main entry point for a request-response process. """ for key in initkwargs: if key in cls.http_method_names: raise TypeError("You tried to pass in the %s method name as a " "keyword argument to %s(). Don't do that." % (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): # 作用:增加属性, 调用dispatch方法 self = cls(**initkwargs) # 创建一个 cls 的实例对象, cls 是调用这个方法的 类(Demo) if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get self.request = request # 为对象增加 request, args, kwargs 三个属性 self.args = args self.kwargs = kwargs 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 def dispatch(self, request, *args, **kwargs): # Try to dispatch to the right method; if a method doesn't exist, if request.method.lower() in self.http_method_names: # 判断请求的方法类视图是否拥有, http_method_names=['get', 'post'] handler = getattr(self, request.method.lower(), self.http_method_not_allowed) # 如果存在 取出该方法 else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) # 执行该方法
简化版
@classonlymethod def as_view(cls, **initkwargs): # 实际上是一个闭包 返回 view函数 """ Main entry point for a request-response process. """ def view(request, *args, **kwargs): # 作用:增加属性, 调用dispatch方法 self = cls(**initkwargs) # 创建一个 cls 的实例对象, cls 是调用这个方法的 类(Demo) if hasattr(self, 'get') and not hasattr(self, 'head'): self.head = self.get self.request = request # 为对象增加 request, args, kwargs 三个属性 self.args = args self.kwargs = kwargs return self.dispatch(request, *args, **kwargs) # 找到指定的请求方法, 并调用它 return view def dispatch(self, request, *args, **kwargs): # Try to dispatch to the right method; if a method doesn't exist, if request.method.lower() in self.http_method_names: # 判断请求的方法类视图是否拥有, http_method_names=['get', 'post'] handler = getattr(self, request.method.lower(), self.http_method_not_allowed) # 如果存在 取出该方法 else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) # 返回该请求方法执行的结果
再简化
def as_view(): # 校验 + 返回view方法 # 一些校验 ... def view(): # 执行视图 # 增加 为对象request, args, kwargs 属性 ... return dispatch() # 调用指定的请求方法 return view def dispatch(): # 真正的查找指定的方法, 并调用该方法 ... return handler()
调用顺序: as_view --> view --> dispatch
- 可以看出
as_view
实际上是一个闭包, 它的作用做一些校验工作, 再返回view
方法.- 而
view
方法的作用是给请求对象补充三个参数, 并调用dispatch
方法处理dispatch
方法查找到指定的请求方法, 并执行可以得出结论: 实际上真正实现查找的方法是
dispatch
方法
高内聚低耦合、生命周期 as_view() => dispatch() => 视图类响应方法