Django Rest Framework(第三天)-APIView源码分析

2.2 APIView源码分析

这里我们还是跟之前分析view源码流程一样:

先从url配置入手分析:

url(r'qk/snippets/$', views.SnippetList.as_view()),

as_view方法代码如下:

原来APIView类是继承View类,view类正式from django.views import View下的View,

先看as_view方法中的view = super(APIView, cls).as_view(**initkwargs)的这行代码, 是调用了父类View中的as_view方法,这里的initkwargs,及其父类的View中的as_view方法执行流程,之类就不在赘述了,简单说就是在如下IndexView类的执行流程,就是之前在分析view流程的整个流程图,重新封装了request对象。

认证信息。主要通过APIView类中的get_authenticators()方法获取,这个方法会返回一个所有认证对象的列表。

rest_framework/settings.py

在rest_framework/authentication.py中定义了几种认证类型,一般情况我们需要自定义认证类,也可以使用django-oauth-toolkit组件进行认证。

dispatch中的initialize_request方法执行完成之后,还有执行一个重要方法是self.initial(request, args, *kwargs),这个方法也是APIView类里的。在这个方法里面初始化 被重新封装的request对象

实现功能: 版本处理 用户认证 权限 访问频率限制

执行APIView里面的perform_authentication方法,该方法返回request.user,则会调用里面的user方法。在user方法里面最终调用了Request类里面的_authenticate方法

rest_framework/request.py

执行rest_framework.request.Request类中的_authenticate方法,这个方法会遍历认证类,并根据认证结果给self.user, self.auth赋值。由于user,和auth都有property属性, 所以给赋值的时候先在先执行setter方法

dispatch中的initial方法执行完之后,会继续判断request.method并执行method相应的method. 执行TestView中定义的get方法,返回数据

调用用完之前的流程之后做了什么操作:

view.cls = cls
view.initkwargs = initkwargs

# Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view)


def csrf_exempt(view_func):
    """Mark a view function as being exempt from the CSRF view protection."""
    # view_func.csrf_exempt = True would also work, but decorators are nicer
    # if they don't have side effects, so return a new function.
    def wrapped_view(*args, **kwargs):
        return view_func(*args, **kwargs)
    wrapped_view.csrf_exempt = True
    return wraps(view_func)(wrapped_view)

csrf_exempt装饰器是我们经常用来做防跨站请求伪造功能。wrapped_view.csrf_exempt = True意思是取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件,然后将csrf_exempt函数中的内置函数wrapped_view赋值wrapped_view.csrf_exempt = True,使其拥有该属性,

接下来看 wraps(view_func)(wrapped_view)函数,

def wraps(wrapped,
          assigned = WRAPPER_ASSIGNMENTS,
          updated = WRAPPER_UPDATES):
    """Decorator factory to apply update_wrapper() to a wrapper function

       Returns a decorator that invokes update_wrapper() with the decorated
       function as the wrapper argument and the arguments to wraps() as the
       remaining arguments. Default arguments are as for update_wrapper().
       This is a convenience function to simplify applying partial() to
       update_wrapper().
    """
    return partial(update_wrapper, wrapped=wrapped,
                   assigned=assigned, updated=updated)



class partial:
    """New function with partial application of the given arguments
    and keywords.
    """

    __slots__ = "func", "args", "keywords", "__dict__", "__weakref__"

    def __new__(*args, **keywords):
        ...

    def __call__(*args, **keywords):
        ...

    ...

wrapped是我们在def csrf_exempt(view_func):函数中的参数,也就是as_view的返回值,

最后通过functools模块下的partial类进行装饰构造,partial 这个东西是针对函数起作用的,偏函数其实就是函数调用的时候,有多个参数,但是其中的一个参数已经知道了,我们可以通过这个参数重新绑定一个新的函数,然后去调用这个新函数。举个例子:

from functools import partial

def add(a,b):
    return a+b

add(4,3)
7

plus = partial(add,100)
plus(9)
109

plus2 = partial(add,99)
plus2(9)
108

同时源码注释中也很明确标注了:

提示: 基于会话的身份验证被明确地CSRF验证 所有其他身份验证都免予使用CSRF。 跳过CSRF验证

也就是说调用父类(View)中的as_view下的view 跳过CSRF验证。


评论(0 ) 点赞(17)


暂未登录,请登录之后发表评论。 QQ