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

浙公网安备 33010602011771号