1、先看代码后讲解:
views部分:
from rest_framework.views import APIView
from django.http import JsonResponse
from API import models
from rest_framework import exceptions
from rest_framework.request import Request
ORDER_DISK = {
#模拟订单数据
"1":{
'name':'猫咪',
'age':3,
'gender':'女',
'content':'......'
},
"2":{
'name':'狗狗',
'age':1,
'gender':'男',
'content':'......'
}
}
class Authtication(object):
def authenticate(self,request):
#user_auth_tuple = authenticator.authenticate(self)跟踪得到,默认调用authenticate方法,返回一个元组,且这个方法被try了捕获一个APIException的异常,所有我们也给他失败抛出一个异常
token = request._request.GET.get('token')
token_obj = models.UserToken.object.filter(token=token).first()
if not token_obj:
raise exceptions.APIException('用户token认证失败!')
return (token_obj.user,token_obj.token)
def authenticate_header(self,request):
'这个方法暂时不知道干啥,不加保存,加上不用先'
pass
class orderView(APIView):
"""
用于处理订单相关业务
"""
authentication_classes = [Authtication,] #DEFAULT_PERMISSION_CLASSES默认去配置文件找,这里自定义一个
def get(self,request,*args,**kwargs):
ret = {'code':1000,'msg':None,'data':None}
try:
ret['data'] = ORDER_DISK
except Exception as e:
pass
return JsonResponse(ret)
urls部分:
from django.contrib import admin
from django.urls import path
from API import views
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/auth/',views.authView.as_view()),
path('api/v1/order/',views.orderView.as_view()),
]
开始解疑:
1、views入口开始,
authentication_classes = [Authtication,] #DEFAULT_PERMISSION_CLASSES默认去配置文件找,这里自定义一个
什么鬼,这个在那里找的,先说这个是rest framework自带的,可以从,dispatch开始找,
还是跟上一篇一样;request封装下面调用了一个initial认证:
def dispatch(self, request, *args, **kwargs): """ `.dispatch()` is pretty much the same as Django's regular dispatch, but with extra hooks for startup, finalize, and exception handling. """ 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
self.initial(request, *args, **kwargs)方法跟进去:
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) self.check_permissions(request) self.check_throttles(request)
上面先不管其他的,最后self.perform_authentication(request)调用了一个认证方法,传进去了request, 再跟进我们发现他返回了一个request.user
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的时候user是个啥!
@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
发现这里又调用了一个其他方法 ,self._authenticate(),跟进去看看:
def _authenticate(self): """ Attempt to authenticate the request using each authentication instance in turn. """ #循环调用了authenticator 且这个方法有点属性。authenticate(self) for authenticator in self.authenticators: try: #可以看出这里捕获一个异常,切返回一个元组 return (self.force_user, self.force_token)可以看到类名ForcedAuthentication 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()
这里就是为什么我们定义一个 Authtication方法authentication_classes = [Authtication,],而且我们定义了这个方法内部也有authenticate方法。也就是我们定义到列表得得方法覆盖系统默认。
那么self.authenticators(注意这里后面带S)又是什么鬼,views中我们没有定义,那么封装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(), #这里可以看到返回了authenticators negotiator=self.get_content_negotiator(), parser_context=parser_context )
跟进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] #这里可以看出,不只是调用一个方法,还是一个列表。
再跟进self.authentication_classes:
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
以上代码可以看出,authentication_classes参数是在api_settings配置的,那么我们知道他是一个列表,是不是可以在视图中自己定义一个,覆盖掉默认。
测试代码:
带token情况:
不带token情况:
这里只是基础的使用方法,下一篇继续更新。