django rest framework系列03-get使用方式基于token基本用户登录状态认证

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情况:

这里只是基础的使用方法,下一篇继续更新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值