DRF源码理解
2019-11-19 本文已影响0人
錦魚
DRF 的 APIView 继承 View
- django 的 View
- DRF 的 APIView
-
dispatch 中,对request进行加强
-
APIView 调用了 View 的 as_view 方法
view = super(APIView, cls).as_view(**initkwargs)
-
View 调用了 APIView 的 dispatch 方法
self.dispatch(request, *args, **kwargs)
-
dispatch 方法加强了原生 request
# 第一次的加强(添加方法) request = self.initialize_request(request, *args, **kwargs) # 第二次的调用(调用方法) self.initial(request, *args, **kwargs)
>>>源码
>>> 第一次的加强(1)
def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
parser_context = self.get_parser_context(request)
# 对request进行了加强
return Request(
request, # Django原本的request
parsers=self.get_parsers(),
authenticators=self.get_authenticators(), # 与认证相关
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
>>> 第一次的加强(2)
# 认证
def get_authenticators(self):
"""
Instantiates and returns the list of authenticators that this view can use.
"""
return [auth() for auth in self.authentication_classes]
# 读配置
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
>>>第二次的调用(1)
def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs)
# Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg
# Determine the API version, if versioning is in use.
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
# Ensure that the incoming request is permitted
self.perform_authentication(request) # 认证 token / 匿名
self.check_permissions(request) # 权限 / 谁能访问什么内容
self.check_throttles(request) # 限流 60/分
>>> 第二次的调用(2)
def perform_authentication(self, request):
"""
Perform authentication on the incoming request.
Note that if you override this and simply 'pass', then authentication
will instead be performed lazily, the first time either
`request.user` or `request.auth` is accessed.
"""
request.user # 验证用户身份方法
>>> 第二次的调用(3)
# rest_framework.request.py 文件内
@property
def user(self):
"""
Returns the user associated with the current request, as authenticated
by the authentication classes provided to the request.
"""
# 列表---> 列表生成式 ---> 一个个对象
if not hasattr(self, '_user'):
with wrap_attributeerrors():
# 获取认证对象 一步步认证
self._authenticate()
return self._user
- 我们可以写一个自己的登录认证
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
class MyAuthentication(BaseAuthentication):
def authenticate(self, request, *args, **kwargs):
if not request._request.GET.get('token') # 拿request 对象的属性:
raise exceptions.AuthenticationFailed('认证失败')
return ("海绵宝宝", None)
# views.py
class xxx(APIView):
authentication_classes = [MyAuthentication]
...
>>> 第二次的调用(4)
def _authenticate(self):
"""
Attempt to authenticate the request using each authentication instance
in turn.
"""
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()
- tips:多认证(多个认同时满足)
- 应用场景:人脸识别、高级安全、资金提现