Django-rest-framework源码分析(三)

 

APIView(二)

  在APIView执行dispatch()方法的时候,它不仅做了分发函数的功能,还进行了一系列的校验。

  Django的全局校验一般写在中间件中,但是rest_framework于Django原生框架而言只是一个应用(Application),它实现全局校验的方法比较特殊,首先规定所有的视图都要以CBV的形式写在类当中,这个类要继承rest_framework的APIView或者继承了APIView的子类。在CBV中我们知道,有一个分发函数dispatch,APIView重写了dispatch,使得dispatch在把请求分配给不同的方法执行之前,先进行了一些校验,虽然这层校验仅仅近似于中间件的process_view,但也达到了全局校验的效果,为我们写全局校验提供了思路,而且这种校验的好处在于,它比较灵活,想进行校验的时候就重写一个dispatch方法,只对某些视图函数进行校验。

  rest_framework/views/class APIView/def dispatch()

  Django-rest-framework源码分析(三)

  dispatch在执行视图函数之前先执行了initial方法

  rest_framework/views/class APIView/def initial()

  Django-rest-framework源码分析(三)

  依次执行了三层校验。分别来看

  rest_framework/views/class APIView/def perform_authentication()

   Django-rest-framework源码分析(三)

  这个函数只是调用了request的user方法(封装成属性的方法)

  rest_framework/request/class Request/def user()

   Django-rest-framework源码分析(三)

  这里也是用了类似单例的模式,避免了重复执行函数,造成资源的浪费。重点看_authenticate

  rest_framework/request/class Request/def _authenticate()

  Django-rest-framework源码分析(三)

  要理解这段源码,还需要再找到Request类的authenticators属性。

  rest_framework/request/class Request/def __init__()

   Django-rest-framework源码分析(三)

  这是Request类的构造函数,当authenticators被传入参数的时候,它被赋值给self.authenticators。而实例化Request对象是在

   Django-rest-framework源码分析(三)

  执行dispatch方法时,我们分析一下调用initialize_request方法的时候都做了什么。

  rest_framework/views/class APIView/def initialize_request()

   Django-rest-framework源码分析(三)

  Request对象被实例化的时候传入了参数,而这个参数是get_authenticators的返回值,get_authenticators做了什么呢?

  rest_framework/views/class APIView/def get_authenticators()

   Django-rest-framework源码分析(三)

  它仅仅只是返回了一个列表推导式,可以推测self.authentication_classes是一个容器类型,里面的元素是一个一个的类,get_authenticators返回的是一个列表,里面是authentication_classes的类实例化出的对象。

  rest_framework/views/class APIView

  Django-rest-framework源码分析(三)

  authentication_classes是作为APIView的类属性出现的,当self进行属性查找的时候,首先查找的是self自身的属性和self所属类的属性,然后是父类APIView的类属性,如果我们在声明类的时候重写了类属性authentication_classes,那么在get_authenticators中得到的就是我们自己写的authentication_classes。如果没写的话,authentication_classes中是什么内容呢?

  rest_framework/settings.py

  Django-rest-framework源码分析(三)

  先看api_settings,它是模块settings中实例化出的一个对象,它是基于模块的单例模式,每次引用api_settings时,都指向同一个内存地址。

  实例化出api_settings的类如下图:

  rest_framework/settings.py/class APISettings

  Django-rest-framework源码分析(三)

  api_settings的default参数被传入了DEFAULTS

  Django-rest-framework源码分析(三)

 

  可以看到api_settings.xxx操作很多时候是直接去DEFAULTS中拿值的。DEFAULTS是一个配置默认设置的字典。也就是说,当我们不自己在声明的类中重写authentication_classes属性的时候,会从settings配置文件中找一个叫"REST_FRAMEWORK的字典",先在这个字典中找有没有相应的属性或者方法,如果没有的话就会走默认值配置的authentication_classes。