• 小谈CBV执行过程


    CBV执行的大致流程

    以 views.Login.as_view() 为例:

    1. 执行views页面中的Login类中的as_view方法
    2. 执行as_view方法中的view方法
    3. 执行dispatch方法
    4. 在dispatch方法中进行判断:
      1. if request.method.lower() in ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']: ==> 通过反射去执行 ;
      2. else ==> return http.HttpResponseNotAllowed(self._allowed_methods())

    CBV执行的具体流程

    还是以 views.Login.as_view() 为例: 在视图中写类时都是继承于View类, 而as_view方法就是View类的一个classonlymethod; 也就是说: 路由中执行的是Login类的父类View中的
    as_view方法 ; 在as_view方法中将Login实例化的对象复制给self, as_view方法的最后调用dispatch方法; dispatch方法判断request.method.lower()是否在8种请求方法中: 如果在, 通过反
    射执行该方法( 就是我们在视图中的Login类下面写的方法 ) ; 如果不在, 就执行http_method_not_allowed方法, 这个方法返回一个http.HttpResponseNotAllowed: 页面会提醒405

    具体代码 :

    class View(object):
       
        ...
       
        @classonlymethod
        def as_view(cls, **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
            return self.dispatch(request, *args, **kwargs)
        
        ...
        
        def dispatch(self, request, *args, **kwargs):
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            return handler(request, *args, **kwargs)
        
        def http_method_not_allowed(self, request, *args, **kwargs):
            logger.warning(
                'Method Not Allowed (%s): %s', request.method, request.path,
                extra={'status_code': 405, 'request': request}
            )
            return http.HttpResponseNotAllowed(self._allowed_methods())
    

    CBV加装饰器

    为视图中的类加装饰器和函数加装饰器情况不同, 尤其是有的装饰器既需要加在函数上, 也需要加在类中方法上. 这时如果不用method_decorator, 可能会导致报错( 因为类中方法比普通函数多一个self
    ).

    # 建议使用method_decorator
    from django.utils.decorators import method_decorator
    

    根据加装饰器的需求不同, 这里粗略的分成三种情况:

    直接加在类中方法上

    # 类中只有一个或者几个方法需要装饰器, 而这个类中有些方法不需要装饰器
    @method_decorator(装饰器名)
    def get(self, request, *args, **kwargs):
    

    直接加在类上

    # 效果和上面差不多, 但是加在类中的某个方法上, 如果是多个方法都需要,可以重复写多个
    @method_decorator(装饰器名,name='类中某个方法名')
    class EditTest(View):
    
    
    # 为类中所有方法都加装饰器: 因为类中方法的执行, 最后都是通过View类中的dispatch方法执行的
    @method_decorator(装饰器名,name='dispatch')
    class EditTest(View):
    

    加在dispatch方法上

    # 效果 和 加在类上,指定方法名为dispatch的方式一样: 为类中方法全部加装饰器
    class EditTest(View):
    
        @method_decorator(装饰器名)
        def dispatch(self, request, *args, **kwargs):
            super(EditTest, self).dispatch(request, *args, **kwargs)
    
  • 相关阅读:
    MapBox TileMill
    优秀电影
    Mapnik 编译安装过程
    Debian 入门安装与配置2
    学习opengl十大网站(转载)
    PostgresSQL 学习资料记录处
    c++模板编程-异质链表
    Linux-统一事件源
    三组I/O复用模型的比较
    ZigZag-LeetCode
  • 原文地址:https://www.cnblogs.com/richard_A/p/12339859.html
Copyright © 2020-2023  润新知