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 的几个主要组件。
网友评论