zoukankan      html  css  js  c++  java
  • django之restframework使用 (三)组件

     认证与权限组件

    认证组件

    局部视图认证

    在app01.service.auth.py:

    class Authentication(BaseAuthentication):
     
        def authenticate(self,request):
            token=request._request.GET.get("token")
            token_obj=UserToken.objects.filter(token=token).first()
            if not token_obj:
                raise exceptions.AuthenticationFailed("验证失败!")
            return (token_obj.user,token_obj)
    

     在views.py:

    def get_random_str(user):
        import hashlib,time
        ctime=str(time.time())
     
        md5=hashlib.md5(bytes(user,encoding="utf8"))
        md5.update(bytes(ctime,encoding="utf8"))
     
        return md5.hexdigest()
     
     
    from app01.service.auth import *
     
    from django.http import JsonResponse
    class LoginViewSet(APIView):
        authentication_classes = [Authentication,]
        def post(self,request,*args,**kwargs):
            res={"code":1000,"msg":None}
            try:
                user=request._request.POST.get("user")
                pwd=request._request.POST.get("pwd")
                user_obj=UserInfo.objects.filter(user=user,pwd=pwd).first()
                print(user,pwd,user_obj)
                if not user_obj:
                    res["code"]=1001
                    res["msg"]="用户名或者密码错误"
                else:
                    token=get_random_str(user)
                    UserToken.objects.update_or_create(user=user_obj,defaults={"token":token})
                    res["token"]=token
     
            except Exception as e:
                res["code"]=1002
                res["msg"]=e
     
            return JsonResponse(res,json_dumps_params={"ensure_ascii":False})
    

    全局视图认证组件

    settings.py配置如下:

    REST_FRAMEWORK={
        "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",]
    }
    

     全局视图下view中的LoginView

    class LoginView(APIView):
        authentication_classes = []
        def post(self,request):
            print('运行POST')
            name=request.data.get("name")
            pwd=request.data.get("pwd")
            user=User.objects.filter(name=name,pwd=pwd).first()
            res = {"state_code": 1000, "msg": None}
            if user:
                random_str=get_random_str(user.name)
                token=Token.objects.update_or_create(user=user,defaults={"token":random_str})
                res["token"]=random_str
            else:
                res["state_code"]=1001 #错误状态码
                res["msg"] = "用户名或者密码错误"
    
            import json
            return Response(json.dumps(res,ensure_ascii=False))
    
    class AuthorModelView(viewsets.ModelViewSet):
    
        authentication_classes = [TokenAuth,]
        permission_classes=[SVIPPermission,]
        #throttle_classes = [VisitRateThrottle]    # 限制某个IP每分钟访问次数不能超过20次
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers
    

     权限组件

    app01.utils.py

    from rest_framework.permissions import BasePermission
    class SVIPPermission(BasePermission):
        message="SVIP才能访问!"
        def has_permission(self, request, view):
            if request.user.user_type==3:
                return True
            return False
    

     views.py

    class AuthorModelView(viewsets.ModelViewSet):
    
        authentication_classes = [TokenAuth,]
        permission_classes=[SVIPPermission,]
        #throttle_classes = [VisitRateThrottle]    # 限制某个IP每分钟访问次数不能超过20次
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers
    

     全局视图权限

    REST_FRAMEWORK={
        "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
        "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",]
    }
    

     如果想添加白名单,在该类下加上permission_classes =[ ]              ,        源码找的时候就会先找这里

    throttle(访问频率)组件

    views.py

    VISIT_RECORD={}
    class VisitThrottle(BaseThrottle):
    
        def __init__(self):
            self.history=None
    
        def allow_request(self,request,view):
            remote_addr = request.META.get('REMOTE_ADDR')
            print('remote_addr',remote_addr)
            import time
            ctime=time.time()
    
            if remote_addr not in VISIT_RECORD:
                VISIT_RECORD[remote_addr]=[ctime,] #列表
                return True
    
            history=VISIT_RECORD.get(remote_addr)
            print('history',history)
            self.history=history
    
            while history and history[-1]<ctime-60:  #时间大于60秒之前的
                history.pop()  #删除
    
            if len(history)<3:  #如果一分钟内访问的次数小于3,就把当前时间加入到history中
                history.insert(0,ctime)
                return True
            else:
                return False
    
        def wait(self):
            import time
            ctime=time.time()
            return 60 - (ctime-self.history[-1])
    
    class AuthorModelView(viewsets.ModelViewSet):
    
        authentication_classes = [TokenAuth,]
        permission_classes=[SVIPPermission,]
        throttle_classes = [VisitThrottle,]    # 限制某个IP每分钟访问次数不能超过20次
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers
    

     全局视图throttle

    REST_FRAMEWORK={
        "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
        "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],
        "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",]
    }
    

    内置throttle类 

    views.py中

    from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
    class VisitThrottle(SimpleRateThrottle):
    
        scope="visit_rate"
        def get_cache_key(self, request, view):
    
            return self.get_ident(request)
    
    class AuthorModelView(viewsets.ModelViewSet):
    
        authentication_classes = [TokenAuth,]
        permission_classes=[SVIPPermission,]
        throttle_classes = [VisitThrottle,]    # 限制某个IP每分钟访问次数不能超过20次
        queryset = Author.objects.all()
        serializer_class = AuthorModelSerializers
    

     setting中

    REST_FRAMEWORK={
        # "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
        # "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],
        # "DEFAULT_THROTTLE_CLASSES":["app01.utils.VisitThrottle",],
        "DEFAULT_THROTTLE_RATES":{
            "visit_rate":"5/m",
        }
    }
    

     解析器

    对得到的数据进行反序列化

    局部视图

    rom rest_framework.parsers import JSONParser,FormParser
    class PublishViewSet(generics.ListCreateAPIView):
        parser_classes = [FormParser,JSONParser]  #只能解析列表中的
        queryset = Publish.objects.all()
        serializer_class = PublshSerializers
        def post(self, request, *args, **kwargs):
            print("request.data",request.data)
            return self.create(request, *args, **kwargs)
    

     全局视图

    REST_FRAMEWORK={
        "DEFAULT_AUTHENTICATION_CLASSES":["app01.service.auth.Authentication",],
        "DEFAULT_PERMISSION_CLASSES":["app01.service.permissions.SVIPPermission",],
        "DEFAULT_THROTTLE_CLASSES":["app01.service.throttles.VisitThrottle",],
        "DEFAULT_THROTTLE_RATES":{
            "visit_rate":"5/m",
        },
        "DEFAULT_PARSER_CLASSES":['rest_framework.parsers.FormParser',]
    }
    

     URL的控制

    url中

    from django.conf.urls import url, include
    from rest_framework import routers
    from tutorial.quickstart import views
    
    router = routers.DefaultRouter()
    router.register(r'authors', views.AuthorsViewSet)
    
    
    urlpatterns = [
        url(r'^', include(router.urls)),
    

     只要注册了router.register,就会有相对应的

    path('authors/',views.AuthorModelView.as_view({'get':'list','post':'create'}),name='authors'),
    re_path(r'^authors/(?P<pk>d+)/$',views.AuthorModelView.as_view({'get':'retrieve','put':'update','delete':'destroy'}),name='authors_detail'),
    

     并且还相应的增加了其他两条restframework的测试url

    分页

    简单分页

    继承APIView类的视图中添加分页

    views.py

    from rest_framework.pagination import PageNumberPagination
    class MyPageNumberPagination(PageNumberPagination):
        # 定义一个PageNumberPagination的子类
        # 如需改变参数,重写其属性即可
        page_size = 6       #每页显示条数
        page_query_param = 'page'   # url中的参数的key
        page_size_query_param="size"    # 可以在url中使用size参数临时改变当页显示的数目
        max_page_size=10 # 可以在url中使用size参数临时改变当页显示的数目,但是最大只能显示10条
     
     
    class AuthorsView(APIView):
        def get(self,request):
            '''分页展示作者列表'''
            author_list = models.Author.objects.all()
            # 分页
            # 实例化一个自己定义的MyPageNumberPagination对象
            pnp = MyPageNumberPagination()
            # 调用paginate_queryset方法来生成新的author_list
            # 参数分别为,author_list,request以及当前的视图
            page_author_list = pnp.paginate_queryset(author_list,request,self)
            # 在将新生成的page_author_list序列化
            auts = serializer.AuthorModelSerializers(page_author_list,many=True)
            return Response(auts.data)
    

     继承ModelViewSet类的视图中添加分页

    views.py

    from rest_framework.pagination import PageNumberPagination
    class Mypagination(PageNumberPagination):
            page_size = 1
            page_query_param = 'page'
            page_size_query_param = "size"
            max_page_size = 5
    
    from rest_framework import viewsets
    class AuthorModelView(viewsets.ModelViewSet):
        queryset = models.Author.objects.all()
        serializer_class = AuthorModelSerializer
        pagination_class = Mypagination
    

    如果我们的视图继承了ModelViewSet类,那么如需分页的时候,只需要在视图类中加入配置参数即可,如下:

       

     

    pagination_class = MyPageNumberPagination    
    

    注意:

        1、MyPageNumberPagination类是我们自己定义的类,见上面一个示例。

        2、pagination_class后面直接跟上类名即可,无需加列表(因为分页不想其他组件,分页只可能有一个)

    全局配置分页属性

    只需要在REST_FRAMEWORK配置中加入 配置属性的键值对即可,如下:

    REST_FRAMEWORK = {
        .....
        "PAGE_SIZE":1
    }
    

     偏移分页

    from rest_framework.pagination import LimitOffsetPagination   # ?offset=1&limit=10
    

    用时只需知名用哪个分页器

    响应器

    from rest_framework.response import Response
    

     帮助我们渲染出页面,更方便操作、调试数据

    I can feel you forgetting me。。 有一种默契叫做我不理你,你就不理我

  • 相关阅读:
    angular、vue使用感受
    API网关在API安全性中的作用
    分享一个国内首个企业级开源的GO语言网关--GoKu API Gateway
    几种部署Goku API Gateway的方式,最快一分钟可使用上网关
    热门开源网关的性能对比:Goku > Kong > Tyk
    如何通过网关做服务编排?
    未来实现API管理系统的几个关键词
    关于未来实现API管理系统的几个关键词
    让API实现版本管理的实践
    医疗行业如何使用API市场?
  • 原文地址:https://www.cnblogs.com/weidaijie/p/10412480.html
Copyright © 2011-2022 走看看