Django Rest Framework(二 认证源码流程)

1、CBV回顾

 

class TestView(APIView): def dispatch(self, request, *args, **kwargs): """ 请求到来以后,都要执行dispatch方法,dispatch方法根据请求方式不一样触发 get/post/put等方法 注意:APIView中的dispatch方法有好多好多的功能 """
        return super().dispatch(request, *args, **kwargs) def get(self, request, *args, **kwargs): return Response('GET请求,响应内容') def post(self, request, *args, **kwargs): return Response('POST请求,响应内容') def put(self, request, *args, **kwargs): return Response('PUT请求,响应内容')

2、使用restful时流程

总体:自建类继承APIView ,APIView又继承View类django

入口:CBV/FBV入口都是urls,由此出发restful

分发:urls 里边使用as_view方法,通过处理到达dispatch方法,在这作分发ide

终点:执行自定义的认证类post

3、图示

 

4、执行详细流程

  • url(r'^test/', TestView.as_view())

进入as_view方法 位置···\site-packages\rest_framework\views.py
  super(APIView, cls).as_view(**initkwargs) 
  调用父类View的as_view() 位置 \site-packages\django\views\generic\base.py
    最终返回 return self.dispatch(request, *args, **kwargs)
this

  • self.dispatch

self是TestView ,没有dispatch方法,继续向APIView找
APIView里边有 url

  • def dispatch()

  ···/site-packages/rest_framework/views.py APIView  def dispatch()spa

 1     def dispatch(self, request, *args, **kwargs):  2  ···  3         # 在这对request作了一下加工
 4         request = self.initialize_request(request, *args, **kwargs) # -->> 对应步骤四、5 -->> 对应步骤四、5
 5  ···  6         # request是丰富后的新request
 7         self.initial(request, *args, **kwargs) # -->> 对应步骤六、七、八、9 -->> 对应步骤六、七、八、9
 8  ···  9         # 根据请求反射取属性,根据method作分发
10         handler = getattr(self, request.method.lower(), 11  self.http_method_not_allowed) 12         response = handler(request, *args, **kwargs)
  • initialize_request()

  initialize_request() ···/site-packages/rest_framework/views.pyrest

 1     def initialize_request(self, request, *args, **kwargs):  2         """
 3  Returns the initial request object.  4  原始request进来,出去是 含request在内的大元祖  5  request基础上增长了parsers、authenticators、negotiator、parser_context四个属性  6  四个属性又对应着四个方法,点击方法进入查看  7         """
 8         parser_context = self.get_parser_context(request)  9         
10         # 把原始的request参数丰富了,利用的是Request类实例化 
11         return Request( 12  request, 13             parsers=self.get_parsers(), 14             authenticators=self.get_authenticators(), #获取用户认证类
15             negotiator=self.get_content_negotiator(), 16             parser_context=parser_context 17         )
  • Request()

  Request() ···\site-packages\rest_framework\request.pycode

 1 class Request(object):  2     def __init__(self, request, parsers=None, authenticators=None,  3                  negotiator=None, parser_context=None):  4  ···  5         self._request = request  #原始request的调用方式
 6         self.parsers = parsers or ()  7         self.authenticators = authenticators or ()  8         self.negotiator = negotiator or self._default_negotiator()  9         self.parser_context = parser_context 10         self._data = Empty 11         self._files = Empty 12         self._full_data = Empty 13         self._content_type = Empty 14         self._stream = Empty 15     # 以上是封装的参数
16     # 此外,还封装了不少方法,一些加了@property
17     # 先看涉及到的parsers、authenticators、negotiator、parser_context 对应的方法
18 
19     def get_parsers(self): 20         """
21  Instantiates and returns the list of parsers that this view can use. 22         """
23         return [parser() for parser in self.parser_classes] 24 
25     def get_authenticators(self): 26         """
27  Instantiates and returns the list of authenticators that this view can use. 28  在这把用户认证类(对象)娶到手了 29         """
30         return [auth() for auth in self.authentication_classes] 31 
32 
33     def get_content_negotiator(self): 34         """
35  Instantiate and return the content negotiation class to use. 36         """
37         if not getattr(self, '_negotiator', None): 38             self._negotiator = self.content_negotiation_class() 39         return self._negotiator 40 
41     def get_parser_context(self, http_request): 42         """
43  Returns a dict that is passed through to Parser.parse(), 44  as the `parser_context` keyword argument. 45         """
46         # Note: Additionally `request` and `encoding` will also be added
47         # to the context by the Request object.
48         return { 49             'view': self, 50             'args': getattr(self, 'args', ()), 51             'kwargs': getattr(self, 'kwargs', {}) 52         }
class Request(object)
  • dispatch()到 initial()

APIView类中:orm

def initial(self, request, *args, **kwargs): self.perform_authentication(request) # 调用认证的方法
  • initial()到perform_authentication()

APIView类中:

def perform_authentication(self, request): # 只有这一句
        request.user

认证走到这了,只有一行request.user 说明是user方法里作的认证
此时request 是新的request 也就是Request() 实例化出来的对象
 进去 Request() 找user方法 看看干了啥
 从APIView() 跳到 Request() 里边了

  • Request() -- user()方法

 @property def user(self): if not hasattr(self, '_user'): with wrap_attributeerrors(): # 执行当前类的_authenticate() 方法
 self._authenticate() return self._user
  • user() 跳到 _authenticate()

  Request() -- _authenticate()方法

def _authenticate(self): # 循环认证全部的类
        for authenticator in self.authenticators: try: # authenticators是上边四、5两步取出来的 用户认证类对象 列表
                # authenticator对象由用户认证类实例化而来,用户认证类确定要支持authenticate()方法
                # 这个方法就是给咱们留的钩子呀,藏得真TM深
                user_auth_tuple = authenticator.authenticate(self) except exceptions.APIException: self._not_authenticated() raise

            if user_auth_tuple is not None: self._authenticator = authenticator self.user, self.auth = user_auth_tuple return self._not_authenticated()

 

整个探索过程当中最重要的是,搞清楚类之间的继承和引用关系,以及不一样类包含相同方法时,到底要执行哪一个类。

遇到实在分不清的,能够打断点看它到底走的哪。不过打断点的前提是对程序总体流程有所了解

相关文章
相关标签/搜索