drf-路由和认证

Posted liqianxin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了drf-路由和认证相关的知识,希望对你有一定的参考价值。

drf-路由

1 路由

针对视图集ViewSet,我们出来可以自己手动指明请求方式与执行函数间的对应关系,还可以使用Routers来快速实现路由信息

Rest-framework提供了两个router:SimpleRouter和DefaultRouter。前者较为简洁,后者产生路由相对较多。

1.1 路由router的使用

路由的配置有三种方式:

# 1 在urls中配置
    url(r‘^books/(?P<pk>d+)‘, views.BookView.as_view(),
    url(r‘^books/‘, views.BooksView.as_view(),
    
# 2 继承了ViewSetMixin,路由就需要指定对应关系
    url(r‘^books/(?P<pk>d+)‘, views.BookView.as_view(actions={‘get‘:‘retrieve‘, ‘put‘:‘update‘,‘delete‘:‘destroy‘})),
    url(r‘^books/‘, views.BooksView.as_view(actions={‘get‘:‘list‘, ‘post‘:‘create‘}))
        
# 3 继承视图类ModelViewSet,路由可以自动生成
    urls.py
        # 第一步:导入routers模块
            from rest)framework import routers
        # 第二步:有两个类,实例化得到对象
            routers.DefaultRouter  生成的路由更多
            routers.SimpleRouter  有两个路由
        # 第三步:注册 router.register(‘前缀‘,‘视图集类‘,‘别名‘)
            router.register(‘books‘,views.BookViewSet)
        # 第四步:拼接到原路由中
            urlpatterns += router.urls

1.2 action的使用

action可以给继承子ModelViewSet的视图类中定义的函数也添加路由

from rest_fromwork.decorates import action

class BookView(ModelViewSet):
    queryset=Book.objects.all()
    serializer_class = BookSerializer
    
    @action(methods=[‘get‘], detail=True)
    def get_1(self, request):
        book = self.get_queryset()[:2]
        ser = self.get_serializer(book, many=True)
        return Response(ser.data)
    
methods中传入的时列表,列表中放的是请求方式。
detail:布尔类型,决定是否在路由中带pk值
    True:xxx/<pk>/action方法名/
    False:xxx/action方法名
    当需要使用pk的时候就设置为True,否则就设置为False

2 认证

2.1 认证的写法

实现认证的步骤:

  1. 写一个类,继承BaseAuthentication,重写authenticate,认证的逻辑卸载里卖弄,认证通过,返回两个值,一个值给了request对象的user,一个给了request对象的auth。认证失败的话,就抛出异常
  2. 全部使用和局部使用

2.2 源码分析

认证、权限、频率的执行代码都是在APIView》dispatch方法》self.initial(request,*args,**kwargs) 中的try下。

‘‘‘
self.perform_authentication(request)为认证源码,内部就只有一句:request.user。需要去drf中Request对象中找user属性。
查找发现,user是一个方法。
‘‘‘
    @property
    def user(self):
        if not hasattr(self, ‘_user‘):  # 刚开始并没有_user
            with wrap_attributeerrors():
                self._authenticate()  # 执行这个
        return self._user

    # 要点
    def _authenticate(self):
        # 遍历拿到self.authenticators认证器对象中一个个验证器进行验证
        # authentication_classes=[认证类1,认证类2]
        for authenticator in self.authenticators:
            try:
                # 认证方法authenticate(self,request)
                # 返回值:登录的用户与认证的信息组成的tuple
                user_auth_tuple = authenticator.authenticate(self)  # 此时的self代表的是request对象
            except exceptions.APIException:
                self._not_authenticated()
                raise

            if user_auth_tuple is not None:
                self._authenticator = authenticator
                # 如何有返回值,就将 登陆用户 与 登陆认证 分别保存到 request.user、request.auth
                self.user, self.auth = user_auth_tuple
                return
            # 如果返回值user_auth_tuple为空,代表认证通过,但是没有 登陆用户 与 登陆认证信息,代表游客
            self._not_authenticated()

2.3 认证组件的使用

# 写一个认证类app_auth.py
from rest_framework.authemtication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app01.models import UserToken

class Authentication_app(BaseAuthentication):
    def authenticate(self, request):
        token = request.GET.get(‘token‘)
        if token:
            user_token = UserToken.objects.fiter(token=token).first()
            if user_token:
                return user_token.user, token
            else:
                raise AuthenticationFailed(‘认证失败‘)
        else:
            raise AuthenticationFailed(‘不含有token‘)
            

# 全局使用和局部使用
    # 全局使用
        REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.app_auth.Authentication_app",]
}
    # 局部使用,在视图类上写
        authentication_classes=[MyAuthentication]
        authentication_classes=[]  # 表示禁用认证。

以上是关于drf-路由和认证的主要内容,如果未能解决你的问题,请参考以下文章

drf框架 6 视图集与路由组件(开发最常用最高级) 三大认证原理 RBAC认证规则

drf--视图,路由

DRF 版本 认证

DRF 认证权限限流分页过滤序列化

微信小程序-drf登录认证组件

Express实战 - 应用案例- realworld-API - 路由设计 - mongoose - 数据验证 - 密码加密 - 登录接口 - 身份认证 - token - 增删改查API(代码片段