zoukankan      html  css  js  c++  java
  • DjangoRestFramework之认证组件,权限组件,频率组件,分页组件

    一 . 认证组件

    我们现在知道的认证机制有cookie, session,session比较安全,session的信息是存在服务器上的,
    如果用户量足够大的话,服务器的压力也就比较大,并且django的session存到了django_session表中,不是很好操作,现在生产中使用的一个叫做token机制的方式比较多.
    可以使用这个机制把token存到用户信息里,当用户登录成功的时候放里面,等他来的时候就要带着这个来,而且们每次来的时候都更新token,防止被拦截.

      我们这里使用一下token,首先要建一个表,和user表一对一关系

      models.py

    class User(models.Model):
        username = models.CharField(max_length=16)
        password = models.CharField(max_length=16)
        types = ((1, 'VIP'), (2, 'SVIP'), (3, 'SSVIP'))
        usertype = models.IntegerField(choices=types, default=1)
    
    class UserToken(models.Model):
        user = models.OneToOneField('User')
        token = models.CharField(max_length=64)

      URL

    url(r'^login/$', views.LoginView.as_view()),  # 别忘了$符号结尾

      视图函数,每次登录后自动刷新token

    import uuid
    
    # 用户登录认证
    class UserAuth(APIView):
        RET = {
            'code': None,
            'userinfo': None,
            'msg': None,
            'token': None
        }
    
        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()
            if user_obj:
                random_str = uuid.uuid4()
                models.UserToken.objects.update_or_create(    # 有就更新,没有就创建
                    user=user_obj,
                    defaults={
                        'token': random_str,
                    }
                )
                self.RET['code'] = 0  # 跟前端约定好,0表示成功
                self.RET['userinfo'] = username
                self.RET['msg'] = 'success'
                self.RET['token'] = random_str
            else:
                self.RET['code'] = -1
                self.RET['userinfo'] = username
                self.RET['msg'] = 'failure'
            return Response(self.RET)

      我们这里写一下DRF的认证组件

    from rest_framework.exceptions import AuthenticationFailed
    from rest_framework.authentication import BaseAuthentication
    from app01 import models
    
    # drf提供认证失败的异常
    class UserAuthToken(BaseAuthentication):
    
        # authenticate方法是固定的,并且必须写这个名字,是request新对象
        def authenticate(self, request):
            token = request.query_params.get('token')  # 类似于GET.get('token')
            token_obj = models.UserToken.objects.filter(token=token).first()
            if token_obj:
                return token_obj.user, token   # 要么就返回两个值,要么就不返回
            else:
                return AuthenticationFailed('认证失败')  

      我们需要把这个认证组件 写到每一个url对应的视图函数中,加上认证,有token就可以访问,没有就拒绝 

    class BookHandle(APIView):
        authentication_classes = [UserAuthToken, ]  #一进到这个函数就进行验证,变量名必须是这个,认证组件需要从所在文件中导入
    
        # 获取所有数据
        def get(self, request):
            book_obj_list = models.Book.objects.all()
            book_res = BookSerializer(book_obj_list, many=True)
            return Response(book_res.data)

      需要补两张成功与失败的对比图!!!

      全局视图组件(写在settings.py中)

      

    二 . 权限组件

      权限组件

    from rest_framework.permissions import BasePermission
    class UserPermission(BasePermission):
        message = "SVIP才能访问!"  # 变量只能叫做message,权限不够的话返回message里面的数据
    
        def has_permission(self, request, view):  # view是用权限的视图函数
            if request.user.usertype == 3:   # user表中usertype的字段表示权限级别
                return True  # 通过权限,只能写True或False
            return False  # 没有通过

      视图函数

    class BookHandle(APIView):
        permission_classes = [UserPer, ]  # 一进函数就验证,只有有权限的才能访问下面的数据
        # 获取所有数据
        def get(self, request):
            book_obj_list = models.Book.objects.all()
            book_res = BookSerializer(book_obj_list, many=True)
            return Response(book_res.data)

      全局视图权限(写在settings.py文件)

    三 . 频率组件 

      内置的throttles类

    from rest_framework.throttling import SimpleRateThrottle
    
    class VisitThrottle(SimpleRateThrottle):
    
        scope="visit_rate"   # 限制访问次数用的
        def get_cache_key(self, request, view):   # 这个方法是固定的
    
            return self.get_ident(request)

      视图函数

    class BookHandle(APIView):
    
        throttle_classes = [VisitThrottle, ]  # 添加访问频率,需要从该类所在位置引入
    
        # 获取所有数据
        def get(self, request):
            book_obj_list = models.Book.objects.all()
            book_res = BookSerializer(book_obj_list, many=True)
            return Response(book_res.data)

    四 .  分页组件 

      视图函数

    from rest_framework.pagination import PageNumberPagination
    
    class BookHandle(APIView):
    
        # 获取所有数据
        def get(self, request):
            book_obj_list = models.Book.objects.all()
            # 创建分页器对象
            pagenum = PageNumberPagination()
            # 通过分页器的paginate_queryset 方法进行分页
            page_book_list = pagenum.paginate_queryset(book_obj_list, request)
            book_res = BookSerializer(page_book_list, many=True)
            return Response(book_res.data)

      可以在全局限制每页显示多少个

      

      当然了,也可以自定义page_size

    from rest_framework.pagination import PageNumberPagination
    class MyPagination(PageNumberPagination):
        # 下面这些参数只能叫固定的名字
        page_size = 3 #每页数据显示条数
        page_query_param = 'pp'  #http://127.0.0.1:8000/books/?pp=1,查询第一页的数据
        page_size_query_param = 'size' # 用做自定义显示数据http://127.0.0.1:8000/books/?pp=2&size=5 #正常是显示3个,这样写就显示5个
        max_page_size = 10 #最大每页展示多少条,即便是你前端通过page_size_query_param临时调整了page_size的值,
                    但是最大也不能超过我们设置的max_page_size的值
    class BookHandle(APIView): # 获取所有数据 def get(self, request): book_obj_list = models.Book.objects.all() pagenum = MyPagination() page_book_list = pagenum.paginate_queryset(book_obj_list, request) book_res = BookSerializer(page_book_list, many=True) return Response(book_res.data)

      继承ModelViewSet的视图函数使用分页器

    from rest_framework.viewsets import ModelViewSet
    from rest_framework.viewsets import ModelViewSet
    
    from rest_framework.pagination import PageNumberPagination
    class MyPagination(PageNumberPagination):
        page_size = 3
        page_query_param = 'pp'
        page_size_query_param = 'size'
        max_page_size = 10
    
    class CAuthorHandle(ModelViewSet):
        queryset = models.Author.objects.all()  # 变量名必须是这个
        serializer_class = AuthorSerializer  # 变量名必须是这个
        pagination_class = MyPagination #配置我们自己写的分页类
  • 相关阅读:
    Unity动态更换图片
    (特殊的)增删改查
    SQL Server 锁
    [转]排序规则
    [转]C#编写Windows服务程序图文教程
    [转]FreeTextBox使用详解 (版本3.1.1)
    [转]Newtonsoft.Json序列化和反序列
    C#性能优化实践(摘抄)
    一、PID控制原理
    POJ 2255已知二叉树前序中序求后序
  • 原文地址:https://www.cnblogs.com/attila/p/10805858.html
Copyright © 2011-2022 走看看