zoukankan      html  css  js  c++  java
  • django rest_framework中的APIView,ModelViewSet,认证,权限,频率,版本

    models.py
    from django.db import models
    
    class UserInfo(models.Model):
        name=models.CharField(max_length=32)
        pwd=models.CharField(max_length=32)
        type_choices=((1,"普通用户"),(2,"VIP"),(3,"SVIP"))
        user_type=models.IntegerField(choices=type_choices,default=1)
    
    
    class Token(models.Model):
        user=models.OneToOneField("UserInfo")
        token = models.CharField(max_length=128)
    
        def __str__(self):
            return self.token
    
    
    class Book(models.Model):
        title=models.CharField(max_length=32)
        price=models.IntegerField()
        pub_date=models.DateField()
        publish=models.ForeignKey("Publisher")
        authors=models.ManyToManyField("Author")
        def __str__(self):
            return self.title
    
    class Publisher(models.Model):
        name=models.CharField(max_length=32)
        email=models.EmailField()
        def __str__(self):
            return self.name
    
    class Author(models.Model):
        name=models.CharField(max_length=32)
        age=models.IntegerField()
        def __str__(self):
            return self.name

    views.py

    from django.shortcuts import render
    
    from app01 import models
    from rest_framework import serializers
    from rest_framework.response import Response
    from rest_framework.views import APIView
    
    class PublisherModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Publisher
            fields = "__all__"
    
    class BookModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
    
    class AuthorModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Author
            fields = "__all__"
    
    #****用户登录认证组件
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.exceptions import AuthenticationFailed
    
    class AuthToken(BaseAuthentication):
    
        def authenticate(self, request):
            token = request.query_params.get('token')   #query_params函数返回的是self._request.GET
            obj = models.Token.objects.filter(token=token).first()
            if not obj:
                raise AuthenticationFailed({'code':1001,'error':'认证失败'})
            return (obj.user.name,obj)
    
    #*********权限组件****
    from rest_framework.permissions import BasePermission
    class SVIPPermission(BasePermission):  #继承于BasePermission,/authous/2/才能查看每个具体的作者。否则报错
        message = "只有超级用户才能访问"
        def has_permission(self,request,view):
            username = request.user
            print(username)
            user_type = models.UserInfo.objects.filter(name=username).first().user_type
            if user_type == 3:
                return True
            else:
                return False
    ##*******频率组件
    # from rest_framework.throttling import BaseThrottle
    # 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)
    #         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)
    #         self.history=history
    #
    #         while history and history[-1]<ctime-60:
    #             history.pop()
    #
    #         if len(history)<10:
    #             history.insert(0,ctime)
    #             return True
    #         else:
    #             return False
    #
    #     def wait(self):
    #         import time
    #         ctime=time.time()
    #         return 60-(ctime-self.history[-1])
    
    
    class PublisherView(APIView):
    
        #获取所有出版社
        def get(self,request):
    
            pub_list = models.Publisher.objects.all()
            pub_ser = PublisherModelSerializer(pub_list,many=True)
            return Response(pub_ser.data)
        #提交出版社
        def post(self,request):
    
            pub_ser = PublisherModelSerializer(data=request.data)
            if pub_ser.is_valid():
                print(pub_ser.validated_data)
                pub_ser.save()
                return Response(pub_ser.data)
            else:
                return Response(pub_ser.errors)
    
    class PublisherDetailView(APIView):
        #查看某个出版社
        def get(self,request,pk):
            pub_obj = models.Publisher.objects.filter(pk=pk).first()
            pub_ser = PublisherModelSerializer(pub_obj)
            return Response(pub_ser.data)
        #更新某个出版社
        def put(self,request,pk):
            pub_obj = models.Publisher.objects.filter(pk=pk).first()
            pub_ser = PublisherModelSerializer(pub_obj,data=request.data)
            if pub_ser.is_valid():
                pub_ser.save()
                return Response(pub_ser.data)
            else:
                return Response(pub_ser.errors)
        #删除某个出版社
        def delete(self,request,pk):
            models.Publisher.objects.filter(pk=pk).delete()
            return Response()
    
    #****解析器
    ###--->根据contenttype的不同解析成不同找到不同的解析器,解析出的是字典或者QueryDict
    ##无论post(请求)前面传的是JSON数据还是urlencoded数据,rest framework 中的request.data都 # 帮我们解析成字典 而django中的request.POST只解析urlencode数据 from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser #默认使用前三个解析器 # 在视图类中添加 parser_classes = [JSONPaser,] #如果只写这一个,意味着只能解析JSON数据 FormParser解析urlencode数据 #*********渲染器***** from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer #在视图类中添加 renderer_classes = [JSONRenderer,] #****响应器就是Response比django原生的HttpResponse多了一些功能 #*******版本*** from rest_framework.versioning import QueryParameterVersioning,URLPathVersioning # versioning_class = URLPathVersioning request.version,获取版本的值推荐用URLPathVersioning不用QueryParameterVersioning # # ******第二种分页 ********* from rest_framework.pagination import PageNumberPagination class MyPageNumberPagination(PageNumberPagination): page_size = 2 # 每页显示多少条数据 page_query_param = "page" # URL中输入的 page=2 page_size_query_param = "size" # 临时浏览器中使用127.0.0.1:8000/books/?page=2&size=2 第二页显示两条数据 max_page_size = 3 # 上面的size最大值,不能无限制显示10000条数据 # # ******第三种分页 ********* from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination class MyLimitOffsetPagination(LimitOffsetPagination): default_limit = 1 #每页显示多少条数据 class BookView(APIView): # authentication_classes = [AuthToken,] # permission_classes = [SVIPPermission,] #依赖于上面的AuthToken # throttle_classes = [] #频率 # parser_classes = [JSONParser, FormParser] #解析器 # renderer_classes = [JSONRenderer,] #渲染器JSONRenderer只返回json数据,不带html页面 # versioning_class = QueryParameterVersioning # def get(self,request): # # book_list = models.Book.objects.all() # # from rest_framework.pagination import PageNumberPagination # # ******第一种分页 不常用********* # #在settings中配置"PAGE_SIZE"的值,定义多少条数据就显示多少 不常用 # pnp = PageNumberPagination() # book_pag = pnp.paginate_queryset(book_list,request,self) # book_ser = BookModelSerializer(book_pag,many=True) # return Response(book_ser.data) def get(self,request,*args,**kwargs): book_list = models.Book.objects.all() #**第二种分页 pnp = MyPageNumberPagination() book_pag = pnp.paginate_queryset(book_list,request,self) book_ser = BookModelSerializer(book_pag,many=True) return Response(book_ser.data) # def get(self,request): # # book_list = models.Book.objects.all() # #**第三种分页 # pnp = MyLimitOffsetPagination() # book_pag = pnp.paginate_queryset(book_list,request,self) # book_ser = BookModelSerializer(book_pag,many=True) # # return Response(book_ser.data) def post(self,request,*args,**kwargs): book_ser = BookModelSerializer(data=request.data) if book_ser.is_valid(): print(book_ser.validated_data) book_ser.save() return Response(book_ser.data) else: return Response(book_ser.errors) class BookDetailView(APIView): def get(self,request,pk,*args,**kwargs): book_obj = models.Book.objects.filter(pk=pk).first() book_ser = BookModelSerializer(book_obj) return Response(book_ser.data) def put(self,request,pk,*args,**kwargs): book_obj = models.Book.objects.filter(pk=pk).first() book_ser = BookModelSerializer(book_obj,data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response(book_ser.errors) def delete(self,request,pk,*args,**kwargs): models.Book.objects.filter(pk=pk).delete() return Response() ##***局部的频率组件 from app01.utils import VisitThrottle from rest_framework import viewsets class BookViewSet(viewsets.ModelViewSet): # authentication_classes = [AuthToken, ] # permission_classes=[SVIPPermission,] throttle_classes = [VisitThrottle] # 限制某个IP每分钟访问次数不能超过20次 queryset = models.Book.objects.all() serializer_class = BookModelSerializer #ModelViewSet中的分页 pagination_class = MyPageNumberPagination import uuid class AuthView(APIView): #authentication_classes = [] # 全局配置后,不让login验证,直接加空列表就不验证 def post(self,request,*args,**kwargs): ##用户登录认证 ret = {'code':1000} user = request.data.get('user') pwd = request.data.get('pwd') user = models.UserInfo.objects.filter(user=user,pwd=pwd).first() if not user: ret['code'] = 1001 ret['error'] = '用户名或密码错误' else: uid = str(uuid.uuid4()) models.Token.objects.update_or_create(user=user,defaults={'token':uid}) ret['token'] = uid return Response(ret)
    utils.py 认证,权限,频率
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.exceptions import AuthenticationFailed
    from app01 import models
    
    #*********用户登录认证组件****
    class AuthToken(BaseAuthentication):
    
        def authenticate(self, request):
            token = request.query_params.get('token')
            obj = models.Token.objects.filter(token=token).first()
            if not obj:
                raise AuthenticationFailed({'code':1001,'error':'认证失败'})
            return (obj.user.name,obj)
    
    #*********权限组件****
    from rest_framework.permissions import BasePermission
    class SVIPPermission(BasePermission):  #继承于BasePermission,/authous/2/才能查看每个具体的作者。否则报错
        message = "只有超级用户才能访问"
        def has_permission(self,request,view):
            username = request.user
            print(username)
            user_type = models.UserInfo.objects.filter(name=username).first().user_type
            if user_type == 3:
                return True
            else:
                return False
    
    
    #*********频率组件****
    from rest_framework.throttling import BaseThrottle
    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)
            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)
            self.history=history
    
            while history and history[-1]<ctime-60:
                history.pop()
    
            if len(history)<10:
                history.insert(0,ctime)
                return True
            else:
                return False
    
        def wait(self):
            import time
            ctime=time.time()
            return 60-(ctime-self.history[-1])
    
    

    setting.py

    REST_FRAMEWORK = {
    
        # "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.TokenAuth",],
        # "DEFAULT_PERMISSION_CLASSES": ["app01.utils.SVIPPermission",],
        # "DEFAULT_THROTTLE_CLASSES":["app01.utils.VisitThrottle",],
        #'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer','rest_framework.renderers.BrowsableAPIRenderer',],
        # "PAGE_SIZE":2,
        'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
        'ALLOWED_VERSIONS':['v1','v2'], # 允许的版本
        'VERSION_PARAM':'version', # 参数
        'DEFAULT_VERSION':'v1', # 默认版本
    }
    #如果加版本url要如下配置(?P<version>w+),如果继承的是APIview,方法中要加*args,**kwargs,
    # 如果不加版本就不用加*args,**kwargs,获取版本用request.version,
    #url(r'^(?P<version>w+)/book/$', views.BookView.as_view()),request.version,获取版本
    
    #url(r'^(?P<version>[v1|v2]+)/users/$', users_list, name='users-list'),这种只能写v1/v2,所以用w+

    urls.py

    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^publisher/$', views.PublisherView.as_view()),
        url(r'^publisher/(d+)/$', views.PublisherDetailView.as_view()),
    
        # url(r'^book/$', views.BookView.as_view()),
        # url(r'^book/(?P<pk>d+)/$', views.BookDetailView.as_view()),
        #加版本
        url(r'^(?P<version>w+)/book/$', views.BookView.as_view()),
        url(r'^(?P<version>w+)/book/(?P<pk>d+)/$', views.BookDetailView.as_view()),
    
    
        url(r'^books/$', views.BookViewSet.as_view({"get":"list","post":"create"}),name="book_list"),
        url(r'^books/(?P<pk>d+)/$', views.BookViewSet.as_view({
                    'get': 'retrieve',
                    'put': 'update',
                    'patch': 'partial_update',
                    'delete': 'destroy'
                }),name="book_detail"),
    
        url(r'^auth/$', views.AuthView.as_view()),
    ]
     
     
  • 相关阅读:
    HDU 2594 Simpsons’ Hidden Talents(辛普森一家的潜在天赋)
    HUD 2203 亲和串
    POJ 3461 Oulipo(乌力波)
    FJNU 1154 Fat Brother And His Love(胖哥与女神)
    Polygon Triangles
    Double it(水题模拟+逆向思维)
    Sphenic numbers(素数筛)
    Desktop(模拟)2016-2017 ACM Central Region of Russia Quarterfinal Programming Contest
    Weather Station(基础DP)2016-2017 ACM Central Region of Russia Quarterfinal Programming Contest
    找零钱(经典DP)
  • 原文地址:https://www.cnblogs.com/chvv/p/10054449.html
Copyright © 2011-2022 走看看