drf 的 cbv View

drf 也可以使用 cbv 这种视图,不过其对 Django 的 view 做了一些封装。drf 最底层的 view 是 APIView,它继承 Django 的 View。所以它的 as_view() 方法与 Django 原生的类似,在它的源码中调用了 super 方法,即 Django view 中的 as_view() 方法,而 view 的 as_view() 在其中写了一个闭包函数返回 view,view 返回 dispatch()。注意这个 dispatch() 是 slef 的,而 self 是当前类的,当前类并没有具体实现,所以可以找到它是在 APIView 中实现的。来看一下 drf 中的 dispatch:

def dispatch(self, request, *args, **kwargs):
    ...
    request = self.initialize_request(request, *args, **kwargs)
    ...
    # 中间有一块与 Django 的一模一样
    return self.response

中间有一个 initialize_request 引起了我们的注意。这个函数干嘛呢?看它的参数是 request,难不成是对 request 做了一层封装:

def initialize_request(self, request, *args, **kwargs):
    parser_context = self.get_parser_context(request)
        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )

原来其确实对 Django 的 request 做了一层封装。我们来看一看 Request 的初始化:

def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
    ...
    self._request = request
    self.authenticators = authenticators or ()
...

可以看到,在 Request 类中将 Django 原始的 request 封装为 _request。所以如果想要调用原生的 request,可以使用 request._request 即可。
回到上一步 initialize_request 中,重点关注 self.get_authenticators(),跟进去:

def get_authenticators(self):
    return [auth() for auth in self.authentication_classes]

返回了一个列表,其中存放类对象。其中 authentication_classes 是默认配置。所以在我们的视图类中可以写 authentication_classes=[] ,表示认证方法。
我们回到 drf 的 dispatch 方法中,发现了另一个函数

self.initial(request, *args, **kwargs)

注意这个 request 已经是封装过的 request 了。追踪进去发现了这样几行代码

self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)

分别表示 认证,权限以及限流,之后会写一片关于 drf 组件的文章里面会提。
先来看一下 perform_authentication,它直接就是 request.user,我们绕道之前说的 Request 封装函数中查看 user 属性

@property
def user(self):
    if not hasattr(self, '_user'):
        with wrap_attributeerrors():
            self._authenticate()
    return self._user

进入 _authenticate():

def _authenticate(self):
    # 尝试依次使用每个验证实例验证请求。
    for authenticator in self.authenticators:
        try:
            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()

drf 写的注释也很好,依次使用每个验证实例来验证请求,前面写到 get_authenticators() 返回一个列表,里面是每个验证对象的实例,这里一次调用了实例的 authenticator 方法,因此我们实现自定义验证方法时,需要实现这个方法,当然还有另一个方法。
下一篇将 drf 的几个主要组件。

你可能感兴趣的:(drf 的 cbv View)