zoukankan      html  css  js  c++  java
  • Django中CBV及其源码解释

    FBV(function base views) 就是在视图里使用函数处理请求。

    CBV(class base views) 就是在视图里使用类处理请求。

    Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。所以Django在后来加入了Class-Based-View。可以让我们用类写View。这样做的优点主要下面两种:

    1. 提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)
    2. 可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性

    CBV源码解析:

    首先,在urls中,我们会有这样一个访问函数:

    path('login/',views.LoginView.as_view() )
    

      当访问login时,django会调用  views.LoginView.as_view() 中 as_view() 这个函数,那么必须先要去看看LoginView中该函数构成:

    class LoginView(View):
        def get(self,request):
    
            return render(request,"login.html")
        def post(self,request):
    
            return HttpResponse("Hello")
    

      LoginView 是我们在视图中创建的类,继承View,LoginView 没有as_view这个方法,于是我们来到继承的父类View,并找到as_view

     1  @classonlymethod
     2     def as_view(cls, **initkwargs):
     3         """Main entry point for a request-response process."""
     4         for key in initkwargs:
     5             if key in cls.http_method_names:
     6                 raise TypeError("You tried to pass in the %s method name as a "
     7                                 "keyword argument to %s(). Don't do that."
     8                                 % (key, cls.__name__))
     9             if not hasattr(cls, key):
    10                 raise TypeError("%s() received an invalid keyword %r. as_view "
    11                                 "only accepts arguments that are already "
    12                                 "attributes of the class." % (cls.__name__, key))
    13 
    14         def view(request, *args, **kwargs):
    15             self = cls(**initkwargs)
    16             if hasattr(self, 'get') and not hasattr(self, 'head'):
    17                 self.head = self.get
    18             self.request = request
    19             self.args = args
    20             self.kwargs = kwargs
    21             return self.dispatch(request, *args, **kwargs)
    22         view.view_class = cls
    23         view.view_initkwargs = initkwargs
    24 
    25         # take name and docstring from class
    26         update_wrapper(view, cls, updated=())
    27 
    28         # and possible attributes set by decorators
    29         # like csrf_exempt from dispatch
    30         update_wrapper(view, cls.dispatch, assigned=())
    31         return view

    从源码中可以看到as_view最后返回了一个view

     此时

    path('login/',views.LoginView.as_view() )    ------->>>>   path('login/',View.view ) 


    当有用户登录Login页面时,dajango会自动调用 View.view

    又找到view的方法,源码如下:
    1  def view(request, *args, **kwargs):
    2             self = cls(**initkwargs)
    3             if hasattr(self, 'get') and not hasattr(self, 'head'):
    4                 self.head = self.get
    5             self.request = request
    6             self.args = args
    7             self.kwargs = kwargs
    8             return self.dispatch(request, *args, **kwargs)
    解读一下view方法:
    self = cls(**initkwargs)  cls为调用as_view时传入的类,为调用该类的对象 LoginView ,这里self为 LoginView 的实例对象.
    return self.dispatch(request, *args, **kwargs)  最后返回的时候,先调用了self.dispatch(request, *args, **kwargs)这个方法.而cls就是LoginView ,一步步找到
    dispatch这个方法

    dispatch源码(分发):
    1     def dispatch(self, request, *args, **kwargs):
    2         # Try to dispatch to the right method; if a method doesn't exist,
    3         # defer to the error handler. Also defer to the error handler if the
    4         # request method isn't on the approved list.
    5         if request.method.lower() in self.http_method_names:
    6             handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    7         else:
    8             handler = self.http_method_not_allowed
    9         return handler(request, *args, **kwargs)
    if request.method.lower() in self.http_method_names:
       handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    其中
    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    获取反射获取到对应的方法('get', 'post', 'put'....)
    最后返回:handler(request, *args, **kwargs) 的调用结果,完成分发
     self.http_method_not_allowed 为错误或找不到值时报错调用的方法
     更多可以查看



  • 相关阅读:
    c# 命令行下编译c#文件 // c# file类读写文件
    C#读取Xml
    System.IO.Path
    System.IO.Path 操作
    关于C#操作INI文件的总结
    C# 文件的一些基本操作(转)//用C#读写ini配置文件
    使用匿名类型做为ComboBox的DataSource
    C# Path 有关于文件路径等问题类(转)
    自考新教材--p60_5_2
    自考新教材--p60_5_1
  • 原文地址:https://www.cnblogs.com/Mixtea/p/10473116.html
Copyright © 2011-2022 走看看