1. 程式人生 > 其它 >drf認證、許可權、頻率、過濾和排序、全域性異常

drf認證、許可權、頻率、過濾和排序、全域性異常

drf認證、許可權、頻率

drf路由

1.簡易版本

# 繼承modelviewmixin 手動配置路由,如下
path('booklogin',views.BookLogin.as_view({'get':'login'}))

檢視類

class BookLogin(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerial
# 派生方法
def login(self, request, *args, **kwargs):

return Response('登入功能')

2.檢視類中的派生方法自動生成路由

路由
from django.contrib import admin
from django.urls import path,include
from app01 import views

from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('booklogin', views.BookLogin)

urlpatterns = [
path('admin/', admin.site.urls),

path('', include(router.urls)),
]

#生成的路由
^booklogin/$ [name='book-list']
^booklogin/login/$ [name='book-login']
^booklogin/(?P<pk>[^/.]+)/$ [name='book-detail']


# 如果檢視類中的引數 @action(methods=['GET', ], detail=True),得到的檢視結果如下
^booklogin/$ [name='book-list']
^booklogin/(?P<pk>[^/.]+)/$ [name='book-detail']
^booklogin/(?P<pk>[^/.]+)/login/$ [name='book-login']
檢視函式
from rest_frame.decorators import action

class BookLogin(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerial
de
# 加個action裝飾器
@action(methods=['GET', ], detail=False)
def login(self, request, *args, **kwargs):

return Response('登入功能')

drf認證

自己寫一個類繼承,BaseAuthentication,看原始碼得知需要重寫其中的authenticate方法

class BaseAuthentication:
"""
All authentication classes should extend BaseAuthentication.
"""

def authenticate(self, request):
"""
Authenticate the request and return a two-tuple of (user, token).
"""
raise NotImplementedError(".authenticate() must be overridden.")

自己寫一個認證類

class LoginAuth(BaseAuthentication):
# 重寫這個方法
def authenticate(self, request):
# 在這裡面寫上認證邏輯
if ... :
return
else:
raise AuthenticationFailed('認證失敗,重試')

然後在檢視類中使用

from rest_framework.decorators import action
from .myauth import LoginAuth



class BookLogin(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerial
# 將自己寫的認證類放入下面這個列表中
authentication_classes = [LoginAuth, ]
認證類的全域性使用和區域性使用
# 全域性使用,在專案的配置檔案中進行配置

# from app01.myauth import LoginAuth
# app01.myauth.LoginAuth # 謹慎防錯

REST_FRAMEWORK = {
#配置響應格式,預設有倆(json,瀏覽器的)
'DEFAULT_RENDERER_CLASSES': [
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],

# 全域性使用寫得認證類
'DEFAULT_AUTHENTICATION_CLASSES':['app01.myauth.LoginAuth'],
}

區域性使用,見上邊那個就是

區域性禁用

當在全域性配置時,如果想使某一個不被認證,就可以區域性禁用,不使用認證

就是在區域性禁用的基礎上,使列表內為空
# 將自己寫的認證類放入下面這個列表中
authentication_classes = []



*******************************************************
from rest_framework.decorators import action
from .myauth import LoginAuth



class BookLogin(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerial


# 登入
@action(methods=['POST', ], detail=False)
def login(self, request, *args, **kwargs):
...
return Response()

認證類原始碼分析

首先記得是drf封裝了一個新的requset物件,重寫了as_view(),但是使用super().as_view(),又重新呼叫了父類的方法--》dispatch方法

# 基本流程

許可權

  • myauth.py

from rest_framework.permissions import BasePermission
# 寫一個類繼承BasePermission,重寫has_permission方法
class MyPermission(BasePermission):

def has_permission(self, request, view):

# 許可權相關邏輯

if request.user.role == 1:
return True
else:
return False
全域性使用和區域性使用
  • 檢視類

# 區域性使用
from .myauth import LoginAuth, MyPermission

class BookLogin(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerial
# 在全域性中配置以後,將這個註釋掉
# authentication_classes = [LoginAuth, ]

# 許可權配置
permission_classes = [MyPermission, ]
  • 全域性使用:專案的配置檔案中

  'DEFAULT_PERMISSION_CLASSES': [
'app01.myauth.MyPermission',
]

補充

def update_or_cretae(self, default=None, **kwargs)
return obj, False

使用:
models.表名.objects.update_or_create(defaults={'xxx': xxxx}, xx=xx)

頻率

  • 自定義頻率類

# 頻率
from rest_framework.throttling import SimpleRateThrottle


class MyThrottling(SimpleRateThrottle):

def get_cache_key(self, request, view):
# 返回什麼就限制什麼,一般可以是使用者id,IP地址等。。
# 返回None就不做限制
return
  • 在檢視類中配置

from .myauth import LoginAuth, MyPermission, MyThrottling


class BookLogin(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerial
# 在全域性中配置以後,將這個註釋掉
# authentication_classes = [LoginAuth, ]

# 許可權配置
permission_classes = [MyPermission, ]
# 頻率
throttle_classes = [MyThrottling, ]

  • 在配置檔案中配置

  # 頻率限制配置資訊
'DEFAULT_THROTTLE_RATES':{
'ip_throttle': '3/m'
}
  • 區域性使用

上述為區域性使用
  • 全域性使用

# 還是在配置檔案中配置
'DEFAULT_THROTTLE_CLASSES': [
'app01.myauth.MyThrottling',
],
'DEFAULT_THROTTLE_RATES':{
'ip_throttle': '3/m',
}

過濾和排序

# 查詢所有才需要過濾和排序

  • 在檢視類中進行配置

# 在檢視類中配置,最頂層的類至少是GenericAPIView
from rest_framework.filters import SearchFilter,OrderingFilter

class BookList(ModelViewSet, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerial
# 在檢視類中配置過濾
filter_backends = [SearchFilter, OrderingFilter]
# 過濾條件,欄位
search_fields = ['name',]

# 排序,欄位
ordering_fields = ['欄位']
  • 篩選,要跟在url中

# 篩選
http://127.0.0.1:8000/booklist/?token=cacb18e4-09d1-4ec0-81c7-9ac46bf8d0a7&search=%E8%AE%BA%E8%AF%AD
  • 過濾外掛
pip3 install django-fliter
  • 使用

# 檢視類
from django_filter.rest_framework import DjangoFilterBackend
class xxx():
...
filter_backends = [DjangoFilterBackend, ]
filter_fields = ['欄位']

全域性異常

1 全域性統一捕獲異常,返回固定的格式  {code:999,msg:'未知錯誤'}

2 使用步驟
-寫一個函式
-在配置檔案中配置



# 寫函式
from rest_framework.views import exception_handler
from rest_framework.response import Response
def common_exception_handler(exc, context):
# 記錄日誌
print(context['request'].META.get('REMOTE_ADDR'))
response=exception_handler(exc, context)
if response: # 處理了drf的異常
data = {'code': 999, 'msg': '錯誤','detail':response.data}
return Response(data)
else: # 不知道的異常
data = {'code':999,'msg':'未知錯誤'}
return Response(data)


# 配置檔案配置

REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'app01.utils.common_exception_handler',
}

拓展

1 看這個原始碼 
from django.contrib.sessions.middleware import SessionMiddleware
2 request.session原始碼
django.contrib.sessions.backends.db.SessionStore

3 內網穿透