DRF权限频率过滤异常处理
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 自定义权限
from rest_framework.permissions import BasePermission
# 自定义权限
class UserPermission(BasePermission):
def has_permission(self, request, view):
if request.user.types == 0: # 0为超级用户,直接返回True
return True
elif request.user.types == 1: # 1为会员用户,只具有'GET'和'POST'的权限
return request.method in ['GET', 'POST']
elif request.user.types == 2: # 2为普通用户,只具有‘GET’权限
return request.method == 'GET'
else:
return False
局部使用:
from app01.utils.auth_check import LogAuthentication
class LoginView(APIView):
# 自定义方法
authentication_classes = []
permission_classes = [LogAuthentication,]
def post(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = User.objects.filter(username=username, password=password).first()
if user:
token = ''.join(str(uuid4()).split('-')).upper()
token_obj = APIToken.objects.update_or_create(defaults={'token': token}, user=user)
return APIResponse(data={'token': token})
else:
return APIResponse(code='103', msg='用户不存在')
全局使用
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [ # 权限的全局配置
# 'app01.utils.permission.UserPermission', # 自定义的权限配置
'rest_framework.permissions.IsAdminUser', # 使用内置的权限配置
],
}
局部禁用
class LoginView(APIView):
# 自定义方法
authentication_classes = []
permission_classes = []
1.3 内置权限的使用(了解)
class Login2View(APIView):
# 内置的方法
authentication_classes = []
permission_classes = []
def post(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = auth.authenticate(username=username, password=password)
if user:
auth.login(request, user)
return APIResponse(msg='登录成功', data={'user': request.user.username})
else:
return APIResponse(code='103', msg='用户不存在')
2 过滤&排序
2.1 过滤
安装第三方模块django-filter
,注意django
的版本需要在 2.2以及之上
pip install django-filter
查看django的版本
>>> import django
>>> print(django.VERSION)
(2, 2, 14, 'final', 0)
局部使用
from django-filter.rest_framework import DjangoFilterBackend
from rest_framework.generics import ListAPIView
class Book3View(ListAPIView):
queryset = Book.objects.all()
serializer_class = GETSerializer
filter_backends = (DjangoFilterBackend,OrderingFilter)
filter_fields = ['name'] # 参与过滤的字段
ordering_fields = ('id','price') # 参与排序的字段
全局使用
# 在app中进行注册
INSTALLED_APPS = [
'rest_framework',
'django-filter', #针对浏览器
]
# REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
# Views.py
class BookView(ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_fields = ('name',) #配置可以按照哪个字段来过滤
2.2 排序
# 局部使用
from rest_framework.filters import OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.generics import ListAPIView
class Book3View(ListAPIView):
queryset = Book.objects.all()
serializer_class = GETSerializer
filter_backends = (DjangoFilterBackend,OrderingFilter)
filter_fields = ['name'] # 参与过滤的字段
ordering_fields = ('id','price') # 参与排序的字段
# 全局配置
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend','rest_framework.filters.OrderingFilter',)
}
3 频率
3.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')
3.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',
}
局部配置:
在视图类中配一个就行
4 异常处理
from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
def api_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)
5 封装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={})