DRF路由、認證、權限、頻率
目錄
路由
原來直接在urls.py中直接.as_view()即可
現在
# 一旦視圖類繼承了ViewSetMixin,則要在路由中配置actions函數
繼承了ModelViewSet的視圖類
# 自動配置路由
from rest_framework import routers
router = routers.SimpleRouter() # SimpleRouter只會生成兩條url
router.register('books','views.BookViewSet') # router.register('前綴','繼承自ModelViewSet的視圖類','別名')
urlpatterns += router.urls
# 另有
router = routers.DefaultRouter() # DefaultRouter會生成六條url
action的使用
from rest_framework.decorators import action
class BookModelViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
@action(methods=['get',],detail=False) # 向'/get_2/'后綴發送列表中注冊的請求時會執行下面函數
def get_2(self,request):
book = self.get_queryset()[:2]
ser = self.get_serializer(book,many=True)
# 如果detail=True,則生成的路由中配置了有名分組pk,需要'/1/get_2'類似的請求,且函數應添加形參pk
認證
# 認證的實現
'''
1.寫一個類,繼承BaseAuthentication類
from rest_framework.authentication import BaseAuthentication
2.重寫authenticate方法,內有認證邏輯,認證通過返回兩個值一個值給request.user,另一個值給request.auth,認證失敗,拋出AuthenticationFailed異常
3.
'''
源碼
# APIView>dispatch>self.initial
self.perform_authentication(request) # >return request.user
class Request #
@property
def user(self):
self._authenticate()
_authenticate():
for authenticator in self.authenticators: # 循環自定義配置的認證類(列表)的認證對象列表
user_auth_tuple = authenticator.authenticate(self) # 這里就用了自己重寫的authenticate方法
寫認證類
# 應用內新建python文件
from rest_framework.authentication import BaseAuthentication
class MyAuthentication(BaseAuthentication):
def authenticate(self, request):
認證類的使用
# 全局使用
from app01.Myauth import MyAuthentication
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'MyAuthentication',
],
}
# 在具體視圖類中定義authentica_classes為空列表可以局部禁用
# 局部使用
# 在視圖類中定義authentication_classes=[]
權限
源碼
# APIView>dispatch>self.initial>self.check_permissions(request)
權限的使用
# 定義權限類
from rest_framework.permissions import BasePermission
class UserAdminPermission(BasePermission):
def has_permission(self, request, view):
user = request.user
# print(user.get_permissions_display())
if user.permissions == 1:
return True
else:
return False
# 局部使用
class NewBooksView(ListAPIView, CreateAPIView):
permission_classes = [UserAdminPermission]
queryset = Book.objects.all()
serializer_class = NewBookModelSerializer
# 全局使用
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'app01.123.UserAdminPermission',
],
}
# 局部禁用
permission_classes = []
內置權限
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAdminUser
class NewBooksView(ListAPIView, CreateAPIView):
authentication_classes = [SessionAuthentication]
permission_classes = [IsAdminUser]
queryset = Book.objects.all()
serializer_class = NewBookModelSerializer
頻率
內置頻率
# 全局使用
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': ['rest_framework.throttling.AnonRateThrottle'],
'DEFAULT_THROTTLE_RATES': {
'anon':'3/m', # 限制匿名用戶每分鐘3次訪問
}
}
# 局部使用
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'anon':'3/m', # 限制匿名用戶每分鐘3次訪問
}
}
class NewNewBooksView(ListAPIView, CreateAPIView):
authentication_classes = [AnonRateThrottle]
queryset = Book.objects.all()
serializer_class = NewBookModelSerializer
# 局部禁用
class NewNewBooksView(ListAPIView, CreateAPIView):
authentication_classes = []
# 如果要使用內置登錄用戶頻率限制,則作用的也只是auth_user
頻率限制
# 新建頻率類繼承SimpleRateThrottle以重寫其內部的get_cache_key方法,并標明配置名稱
from rest_framework.throttling import SimpleRateThrottle
class MyThrottle(SimpleRateThrottle):
scope = 'xxx'
def get_cache_key(self, request, view):# return結果是頻率限制的key
return request.META.get('REMOTE_ADDR')
# 局部配置或者全局配置頻率類
class BookView(ListAPIView):
throttle_classes = [MyThrottle]
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
pagination_class = MYLimitOffsetPagination
# 全局配置對應名稱的頻率值限制
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'xxx': '3/m',
},
}
自定義頻率
from rest_framework.throttling import BaseThrottle
# 自定義頻率類,需要重寫兩個方法,即allow_request、wait
class IPThrottle(BaseThrottle):
visit_dict = {}
def __init__(self):
self.history_list = []
def allow_request(self, request, view):
ip = request.META.get('REMOTE_ADDR')
ctime = time.time()
if ip not in self.visit_dict:
self.visit_dict[ip] = [ctime,]
return True
self.history_list = self.visit_dict[ip]
while True:
if ctime-self.history_list[-1]>60:
self.history_list.pop()
else:
break
if len(self.history_list)<2: # 配置一個周期內的頻次限制
self.history_list.insert(0,ctime)
return True
else:
return False
def wait(self):
ctime = time.time()
return 60 - (ctime-self.history_list[-1])
from utils.throttle1 import IPThrottle
class BookView(ListAPIView):
throttle_classes = [IPThrottle]
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
pagination_class = MYLimitOffsetPagination
浙公網安備 33010602011771號