Django REST framework是基于CBV模式实现的
Django REST framework和django的区别
先来看看认证部分
普通的CBV:
from django.views import View
class Eg(View):
def get(self,request,*args,**kwargs):
return HttpResponse("GET")
Django REST framework的CBV:
from rest_framework.views import APIView
class Eg(APIView):
def get(self,request,*args,**kwargs):
return HttpResponse("GET")
可以看出只是继承父类不同
查看APIView可发现class APIView(View)
,可以理解为APIview是对View的扩展或者是修改
Django REST framework自定义认证类使用示例
路由:''re_path('^eg/$',views.Eg.as_view())''
''
from rest_framework.views import APIView
from rest_framework.authentication import BaseAuthentication
class MyAuthenticate(BaseAuthentication):
'''自定义认证类'''
def authenticate(self,request):
token=request._request.GET.get('token') #request._request是原生request
#token=request.query_params.get('token') 效果一样request._request.GET==request.query_params
if not token:
raise exceptions.AuthenticationFailed("用户登录失败")
return ('yue',18) #第一个元素通常是数据库表的一行数据,也就是一个类对象
class Eg(APIView):
'''视图'''
authentication_classes = [MyAuthenticate,] #局部使用自定义认证类
def get(self,request,*args,**kwargs):
print(request.user) #认证类返回的元组的第一个元素
return HttpResponse("GET")''
全局使用:REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ('api.auth.MyAuthenticate'), #注意是认证类路径
}
Django REST framework认证源码解析
首先,DRF一般都是CBV的模式。以普通视图为例(继承APIView,APIView继承了View,重写了dispatch方法,所以可以说DRF是对Django的一个扩展)。按生命周期开始,request到达之后,由wsgi解析请求信息,经过中间件,到达路由(re_path(’^eg/$’,views.Eg.as_view())),执行APIView的类方法as_view,在内部有执行父类View的类方法as_view,返回了一个view方法,变成了FBV模式(re_path(’^eg/$’,views.view)),view方法是View类里的内置方法,里面调用了self.dispatch(self.dispatch(request, *args, **kwargs)),根据继承关系,执行APIView的dispatch方法
''def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
self.initial(request, *args, **kwargs)
# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response''
首先看request = self.initialize_request(request,),执行APIView的initialize_request方法
def initialize_request(self, request, *args, **kwargs):
"""
Returns the initial request object.
"""
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
)
返回的是一个Request类对象,其中对原生request做了封装和丰富,里面有原生request和别的
先看一下和认证相关的authenticators=self.get_authenticators()。
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
默认是一个Django REST framework配置文件类对象的列表,如果自己定义了authentication_classes
就用的自己的
然后回到dispatch继续往下走
try:
self.initial(request, *args, **kwargs) #这里的request是处理后的,包含原生request,类对象列表和其他
。initial
方法里有self.perform_authentication(request)
perform_authentication
方法内容
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
这里的request是Request类的一个对象,user是Request的一个静态方法,所以可以不加括号调用
@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
再看_authenticate方法
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()
可以看到是对self.authenticators
循环处理,self.authenticators
就是authentication_classes
类对象列表
这里以自定义认证类(可多个)为例:
循环执行每个认证类的authenticate方法:
1.抛异常,_authenticate捕获,raise继续往上抛
2.有返回值,必须是元组,包含两个元素(想返回什么都可以。一般第一个是数据库对象,方便后续直接使用),由self.user, self.auth = user_auth_tuple
处理对应request.user,request.auth,可以在处理函数里面直接使用
3.没有返回值,默认返回None,执行下个认证类。都是None的话执行_not_authenticated,设置默认值,AnonymousUser和None(可在配置文件中修改)(UNAUTHENTICATED_USER=None, UNAUTHENTICATED_TOKEN=None)