1. 程式人生 > 實用技巧 >Django---drf許可權、頻率

Django---drf許可權、頻率

目錄

昨日回顧

# 1 路由
# 2 3種寫法  
	-django傳統的路由(cbv路由)path('test/', views.TestView.as_view()),
    -只要繼承ViewSetMixin:path('books/', views.BookViewSet.as_view({'get':'list','post':'create'})),
    -自動生成路由
    	-SimpleRouter
        -DefaultRouter
        -使用:
        	# 第一步:匯入routers模組
            from rest_framework import routers
            # 第二步:有兩個類,例項化得到物件
            # routers.DefaultRouter 生成的路由更多
            # routers.SimpleRouter
            router=routers.SimpleRouter()
            # 第三步:註冊
            # router.register('字首','繼承自ModelViewSet檢視類','別名')
            router.register('books',views.BookViewSet) # 不要加斜槓了
            urlpatterns+=router.urls
#3 action的使用:裝飾器給繼承了ModeViewSet的檢視類中自定義的方法,自動生成路由
#4 method=['get','post'],detail=True(帶pk的)/False(不帶pk)

# 5 認證
	-使用
    	-定義一個類,繼承BaseAuthentication,重寫def authenticate(self, request),校驗成功返回兩個值,一個是user物件,第二個是token
        -需要注意,如果配置多個認證類,要把返回兩個值的放到最後
        -全域性使用:setting配置
            REST_FRAMEWORK={
        	"DEFAULT_AUTHENTICATION_CLASSES":["app01.app_auth.MyAuthentication",],
    			}
        -區域性使用:
        authentication_classes=[MyAuthentication]
        -區域性禁用:authentication_classes = []

今日內容

1 許可權

1.1 許可權原始碼分析

# APIView---->dispatch---->initial--->self.check_permissions(request)(APIView的物件方法)
    def check_permissions(self, request):
        # 遍歷許可權物件列表得到一個個許可權物件(許可權器),進行許可權認證
        for permission in self.get_permissions():
            # 許可權類一定有一個has_permission許可權方法,用來做許可權認證的
            # 引數:許可權物件self、請求物件request、檢視類物件
            # 返回值:有許可權返回True,無許可權返回False
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request, message=getattr(permission, 'message', None)
                )

1.2 許可權的使用

# 寫一個類,繼承BasePermission,重寫has_permission,如果許可權通過,就返回True,不通過就返回False
from rest_framework.permissions import BasePermission

class UserPermission(BasePermission):
    def  has_permission(self, request, view):
        # 不是超級使用者,不能訪問
        # 由於認證已經過了,request內就有user物件了,當前登入使用者
        user=request.user  # 當前登入使用者
        # 如果該欄位用了choice,通過get_欄位名_display()就能取出choice後面的中文
        print(user.get_user_type_display())
        if user.user_type==1:
            return True
        else:
            return False
        
# 區域性使用
class TestView(APIView):
    permission_classes = [app_auth.UserPermission]
# 全域性使用
REST_FRAMEWORK={
    "DEFAULT_AUTHENTICATION_CLASSES":["app01.app_auth.MyAuthentication",],
    'DEFAULT_PERMISSION_CLASSES': [
        'app01.app_auth.UserPermission',
    ],
}
# 區域性禁用
class TestView(APIView):
    permission_classes = []

1.3 內建許可權(瞭解)

# 演示一下內建許可權的使用:IsAdminUser,控制是否對網站後臺有許可權的人
# 1 建立超級管理員
# 2 寫一個測試檢視類
from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication
class TestView3(APIView):
    authentication_classes=[SessionAuthentication,]
    permission_classes = [IsAdminUser]
    def get(self,request,*args,**kwargs):
        return Response('這是22222222測試資料,超級管理員可以看')
# 3 超級使用者登入到admin,再訪問test3就有許可權
# 4 正常的話,普通管理員,沒有許可權看(判斷的是is_staff欄位)

2 頻率

2.1 內建的頻率限制(限制未登入使用者)

# 全域性使用  限制未登入使用者1分鐘訪問5次
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',
    ),
    'DEFAULT_THROTTLE_RATES': {
        'anon': '3/m',
    }
}
##############views.py
from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication,BasicAuthentication
class TestView4(APIView):
    authentication_classes=[]
    permission_classes = []
    def get(self,request,*args,**kwargs):
        return Response('我是未登入使用者')

# 區域性使用
from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication,BasicAuthentication
from rest_framework.throttling import AnonRateThrottle
class TestView5(APIView):
    authentication_classes=[]
    permission_classes = []
    throttle_classes = [AnonRateThrottle]
    def get(self,request,*args,**kwargs):
        return Response('我是未登入使用者,TestView5')

2.2 內建頻率限制之,限制登入使用者的訪問頻次

# 需求:未登入使用者1分鐘訪問5次,登入使用者一分鐘訪問10次
全域性:在setting中
  'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle'
    ),
    'DEFAULT_THROTTLE_RATES': {
        'user': '10/m',
        'anon': '5/m',
    }
        
 區域性配置:
	在檢視類中配一個就行

3 過濾

#1 安裝:pip3 install django-filter
#2 註冊,在app中註冊
#3 全域性配,或者區域性配
 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
#4 檢視類
class BookView(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_fields = ('name',)  #配置可以按照哪個欄位來過濾

4 排序

# 區域性使用和全域性使用
# 區域性使用
from rest_framework.generics import ListAPIView
from rest_framework.filters import OrderingFilter
from app01.models import Book
from app01.ser import BookSerializer
class Book2View(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [OrderingFilter]
    ordering_fields = ('id', 'price')
    
# urls.py
path('books2/', views.Book2View.as_view()),
]

# 使用:
http://127.0.0.1:8000/books2/?ordering=-price
http://127.0.0.1:8000/books2/?ordering=price
http://127.0.0.1:8000/books2/?ordering=-id

5 異常處理

#統一介面返回

# 自定義異常方法,替換掉全域性
# 寫一個方法
# 自定義異常處理的方法
from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
def my_exception_handler(exc, context):
    response=exception_handler(exc, context)
    # 兩種情況,一個是None,drf沒有處理
    #response物件,django處理了,但是處理的不符合咱們的要求
    # print(type(exc))

    if not response:
        if isinstance(exc, ZeroDivisionError):
            return Response(data={'status': 777, 'msg': "除以0的錯誤" + str(exc)}, status=status.HTTP_400_BAD_REQUEST)
        return Response(data={'status':999,'msg':str(exc)},status=status.HTTP_400_BAD_REQUEST)
    else:
        # return response
        return Response(data={'status':888,'msg':response.data.get('detail')},status=status.HTTP_400_BAD_REQUEST)
    
# 全域性配置setting.py
'EXCEPTION_HANDLER': 'app01.app_auth.my_exception_handler',

6 封裝Response物件(重要)

# 以後都用自己封裝的
class APIResponse(Response):
    def __init__(self,code=100,msg='成功',data=None,status=None,headers=None,**kwargs):
        dic = {'code': code, 'msg': msg}
        if  data:
            dic = {'code': code, 'msg': msg,'data':data}
        dic.update(kwargs)
        super().__init__(data=dic, status=status,headers=headers)
# 使用
return APIResponse(data={"name":'lqz'},token='dsafsdfa',aa='dsafdsafasfdee')
return APIResponse(data={"name":'lqz'})
return APIResponse(code='101',msg='錯誤',data={"name":'lqz'},token='dsafsdfa',aa='dsafdsafasfdee',header={})

補充

1 變數後直接加逗號

a=(3,)
a=3,  # a是元組
print(type(a))

作業

1 檢視類繼承GenericAPIView,get方法,post方法,用的序列化類不一樣

2 圖書一堆關聯表的增刪查改寫完book表,author表,authordetail表,publish表,中間表

3 過濾,排序,認證,許可權,頻率,異常處理