美文网首页
drf 的 cbv View

drf 的 cbv View

作者: vckah | 来源:发表于2018-06-12 23:12 被阅读0次

    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

          本文链接:https://www.haomeiwen.com/subject/obqdeftx.html