Django---drf許可權、頻率
阿新 • • 發佈:2020-07-10
目錄
昨日回顧
# 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))