zoukankan      html  css  js  c++  java
  • drf路由与认证

    一、路由

    三种路由配置

    1 没有继承视图集的视图类

    # urls.py
    path('books4/', views.Book4View.as_view()),
    re_path('books4/(?P<pk>d+)', views.Book4DetailView.as_view())
    

    2 继承了视图集的视图类

    # urls.py
    path('books5/', views.Book5View.as_view(actions={'get':'list','post':'create'})), #当路径匹配,又是get请求,会执行Book5View的list方法
    re_path('books5/(?P<pk>d+)', views.Book5View.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})),
    # 这里的方法名可以修改
    

    3 继承自ModelViewSet的路由写法(自动生成)

    # 1 
    # 导入routers类
    from rest_framework import routers
    
    # 2
    # 实例化得到routers对象
    # 这种比下面simple多几个没用的路由
    # router = routers.DefaultRouter()
    # 只有两个路由,一个是带pk参数,一个不带参数
    # ^student4/$ [name='student-list']   student4/
    # ^student4/(?P<pk>[^/.]+)/$ [name='student-detail']  student4/4/
    router = routers.SimpleRouter()
    
    # 3
    # 注册 router.register('前缀','继承自ModelViewSet视图类','别名')
    router.register('student4',views.Students4API)
    
    # 4
    urlpatterns+=router.urls
    

    action参数

    # 当我们需要自定义方法名也能自动生成路由的时候
    from rest_framework.decorators import action
    # methods:放一个需要对于的请求列表
    # detail=True 带pk参数,False 不带pk参数
    @action(methods=['GET'],detail=True)
        def get_xxx(self,request,pk):
            return Response({'pk':pk})
    

    二、认证

    1 drf认证的源码分析

    # 分析APIView重写的dispatch方法,发现它添加了一个initial方法,这个方法内涵了drf的三大校验:认证,权限,频率
    # 点进去这个方法,删掉没用的,发现最后就调用了这三个方法,第一个是认证的方法
        def initial(self, request, *args, **kwargs):
            self.perform_authentication(request)
            self.check_permissions(request)
            self.check_throttles(request)
    # perform_authentication内部只有一个代码就是request.user
    # 这里要注意,APIView重写了request,所以这里看到的request实际上是drf写的
    # 所以我们在找user的时候要去drf的Request类中
    # 最后发现user原来是一个被封装成属性的方法
     @property
        def user(self):
            # 如果request没有_user属性,执行self._authenticate()
            # 到Request的__init__方法看,果然没有
            if not hasattr(self, '_user'):
                with wrap_attributeerrors():
                    self._authenticate()
            return self._user
    # 最后我们点到_authenticate()方法,再展开这个方法前,我们需要找到其中最关键的参数authenticators
    # 先去实例化的对象里,也就是dispatch内定义的request找
    # 是通过一个initialize_request方法实例化了request
    # 在这里发现了我们要找的authenticators
    # 是调用了get_authenticators得到的
    # 内部返回了一个[auth() for auth in self.authentication_classes]
    # 这是一个列表生成式,循环self.authentication_classes,对象内没有这个属性,去Request类中找
    # 发现他的来源是api_settings.xxx
    # 这里就不再展开了,只要知道这是一个配置的常量,内部是一个列表,存放着我们要认证的类
    # 查找顺序是先从视图类(局部),其次项目settings(全局),最后apisettings(默认)
    # 只要在一个地方配置了,就会向下覆盖
    # 再回到这个列表生成式,是调用了存放在列表中的认证类,在把实例化的对象放入新的列表authenticators
     def _authenticate(self):
        	# 循环拿到的是一个个认证对象
            for authenticator in self.authenticators:
                try:
                    # 调用了认证对象的authenticate,把request传进去
                    user_auth_tuple = authenticator.authenticate(self)
                except exceptions.APIException:
                    # 如果没有这个方法,就会抛异常,所以从这里可以知道,如果要自定义认证类,就必须重写类中的authenticate方法
                    # 并按固定格式返回数据
                    self._not_authenticated()
                    raise
    			# 把返回的参数赋值给request,第一个参数默认必须是用户,第二个随便
                if user_auth_tuple is not None:
                    self._authenticator = authenticator
                    self.user, self.auth = user_auth_tuple
                    return
              # 如果返回值user_auth_tuple为空,代表认证通过,但是没有登陆用户与登陆认证信息,代表游客
            self._not_authenticated()
    
    

    2 自定义认证类的使用

    # 自定义认证类
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.exceptions import AuthenticationFailed
    class TokenAuthentication(BaseAuthentication):
        def authenticate(self,request):
            token = request.GET.get('token')
            username = request.GET.get('username')
            obj = UserToken.objects.filter(token=token)
            user = User.objects.filter(username=username).first()
            if obj:
                return user,obj
            else:
                raise AuthenticationFailed('认证失败')
    

    view.py

    class Students2API(GenericAPIView,ListModelMixin,CreateModelMixin):
        queryset = models.Student.objects
        serializer_class = ser.StudentModelSerializer
        authentication_classes = [TokenAuthentication]
        # 局部配置
        def get(self,request):
            return self.list(request)
        def post(self,request):
            return self.create(request)
    class Student2API(GenericAPIView,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin):
        queryset = models.Student.objects
        serializer_class = ser.StudentModelSerializer
        def put(self,request,pk):
            return self.update(request,pk)
        def get(self,request,pk):
            return self.retrieve(request,pk)
        def delete(self,request,pk):
            return self.destroy(request,pk)
        
    class UserAPI(APIView):
        # 登录视图
        def post(self,request):
            username = request.data.get('username')
            password = request.data.get('password')
            user_obj = models.User.objects.filter(username=username,password=password).first()
            back_dic = {'code':200,'msg':'登录成功'}
            if user_obj:
                # 登录成功
                import uuid
                token = uuid.uuid4()
      models.UserToken.objects.update_or_create(user=user_obj,defaults={'token':token})
                back_dic['user'] = username
                back_dic['token'] = token
            else:
                back_dic['msg'] = '账号或密码错误'
            return Response(back_dic)
    
  • 相关阅读:
    转--Android中调用webservice的工具类
    转--Android实现ListView过滤功能,继承于BaseAdapter,非ArrayAdapter。
    Kubernetes 1.5 配置dns
    Kubernetes 1.5安装
    HAproxy健康检查的三种方式
    某电商网站线上drbd+heartbeat+nfs配置
    sonarqube代码检测
    Sersync实时同步
    RabbitMQ配置文件
    SVNManager配置
  • 原文地址:https://www.cnblogs.com/hz2lxt/p/13275564.html
Copyright © 2011-2022 走看看