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 内网穿透



posted @ 2021-07-06 21:05  代码歌  阅读(317)  评论(0)    收藏  举报