zoukankan      html  css  js  c++  java
  • django的as_view方法实现分析

    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方法



  • 相关阅读:
    代码实现:海滩上有一堆桃子,五只猴子来分。第一只猴子把这堆桃子凭据分为五份,多了一个,这只猴子把多的一个扔入海中,拿走了一份。 第二只猴子把剩下的桃子又平均分成五份,又多了一个,它同样把多的一个扔入海中,拿走了一份, 第三、第四、第五只猴子都是这样做的,问海滩上原来最少有多少个桃子?
    代码实现:编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n
    一款炫酷Loading动画--载入成功
    [魅族Degao]Androidclient性能优化
    Spring2.5学习3.2_编码剖析@Resource注解的实现原理
    freemarker写select组件报错总结(六)
    storm笔记:Storm+Kafka简单应用
    2014-8-4阿里电话面试
    UML--组件图,部署图
    CentOS7.1 KVM虚拟化之经常使用管理虚拟机命令(3)
  • 原文地址:https://www.cnblogs.com/ellisonzhang/p/10668486.html
Copyright © 2011-2022 走看看