Django中CBV的基本使用与源码分析

CBV:基于类的视图

Django中视图函数并不一定就是函数,也可以是类。

什么!你想问什么是类!?

image

CBV的基本写法

from django.views import View

class Login(View):
  def get(self, request):
    return render(request, 'login.html')
  def post(self, request):
    return HttpResponse('我是类里面的post方法')
url(r'^login/', views.Login.as_view())

当我们朝login提交get请求时,会执行Login中的get方法,而朝login提交post请求时会执行其中的post方法。


image

那么到底为什么Login会针对不同的请求自动执行对应的方法呢?

我们通过对路由来分析

url(r'^login/', views.Login.as_view())

从路由表面应该不难看出,Login可能是通过了as_view()这个方法实现了它的全自动分拣功能!

这里as_view()这个方法应该有两种可能:

1. as_view()可能是类里面定义的普通方法staticmethod,
2. as_view()可能是类里面定义的绑定给类的方法classmethod。

让我们来瞜一眼源码~~~

@classonlymethod
def as_view(cls, **initkwargs):

果然他是classmethod


image

接下来我们来看一下他到底是怎么实现的呢?

as_view

"""
通过以下方法return的内容,我们首先得出一个结论
url(r'^login/', views.Login.as_view())  等价于 url(r'^login/', views.view)
而当发生请求时,首先执行的时as_view方法
"""
@classonlymethod
def as_view(cls, **initkwargs):
                pass
  def view(request, *args, **kwargs):
    # cls是我们自己写的Login类,产生的self对象就是Login(**initkwargs)
    self = cls(**initkwargs)
    if hasattr(self, 'get') and not hasattr(self, 'head'):
      # 以下四句话是在给我们创建的类设置属性
      self.head = self.get
      self.request = request
      self.args = args
      self.kwargs = kwargs
        """
        这里的self使我们创建的Login产生的对象,根据对象查找属性和方法的顺序
        首先找对象自己,如果没有再到自己的类中查找,自己的类中没有再查找父类的名称空间中的dispatch方法
        """
      return self.dispatch(request, *args, **kwargs)
    view.view_class = cls
    view.view_initkwargs = initkwargs
  
    update_wrapper(view, cls, updated=())

    update_wrapper(view, cls.dispatch, assigned=())
    return view
image

整个cbv的精髓都在下面这几句代码中

dispatch

def dispatch(self, request, *args, **kwargs):
    # 判断当前请求是否符合http_method_names中默认的八个请求方式
    if request.method.lower() in self.http_method_names:
            # handler = getattr(我们自己写的类产生的对象,'get', 报错信息)(以get为例,post同理)
            # handeler就是通过反射获得的自己类里面的get方法
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
        # 返回报错信息
            handler = self.http_method_not_allowed
    # 调用类里面的get方法
    return handler(request, *args, **kwargs)

这样就实现了该方法的全天候全自动筛检功能!


image
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容