drf权限、封装、过滤、排序、异常处理、Rsponse封装
1、权限
1.1、权限源码解析
源码位置:APIView=》dispatch=》initial===》self.check_permissions(request) (APIView的对象方法)
可以通过源码看出先是遍历权限对象列表得到一个个权限对象(也就是权限器),新型权限认证
权限类有一个has_permission的权限认证方法,用来判断是否有权限
涉及到的参数:权限对象self,请求对象request,以及视图类对象
返回值:有权限就返回True,无权限返回False
def check_permissions(self, request):
for permission in self.get_permissions():
if not permission.h
(request, self):
self.permission_denied(
request, message=getattr(permission, 'message', None)
1.2、权限的使用
先在app_auth写一个类,用来继承Basepermission,重写has_permission,根据前端传送过来的数据的user_type进行对比,如果权限通过,就返回True,无权限就返回False
from rest_Permission(BasePermission):
class Userpermission(BasePermission)
def has_permission(self,request,view):
user = request.user
print(user.get_user_type_disproy()) #可以获取用户choice后面的中文
if user.user_type == 1:
return True
else:
return False
1.3、全局使用和局部使用
局部使用:
class Test(APIView):
permission_classes = [app_auth.UserPermission]
全局使用:
REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":["app01.app_auth.MyAuthentication",],
'DEFAULT_PERMISSION_CLASSES': [
'app01.app_auth.UserPermission',
],
}
局部禁用:
class TestView(APIView):
permission_classes = []
1.4、内置权限(了解)
# 演示一下内置权限的使用:IsAdminUser,控制是否对网站后台有权限的人
# 1 创建超级管理员
# 2 写一个测试视图类
from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication
class TestView3(APIView):
authentication_classes=[SessionAuthentication,]
permission_classes = [IsAdminUser]
def get(self,request,*args,**kwargs):
return Response('这是22222222测试数据,超级管理员可以看')
# 3 超级用户登录到admin,再访问test3就有权限
# 4 正常的话,普通管理员,没有权限看(判断的是is_staff字段)
2、频率
2.1、内置的频率限制(限制未登录用户)
频率功能是内置的,直接使用就行,主要分为全局使用和局部使用
1.全局使用
1.在setting中设置
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'anon': '3/m',
}
}
2.由于是未登录用户,所以需要将views.py中认证功能和权限功能都关闭
from rest_framework.permissions import IsAdminuser
from rest_framework.Authentication import SessionAuthentication
class Testview(APIView):
authentication_classes = [] #关闭认证功能
permission_class = [] #关闭权限功能
def get(self,request,*args,**kwargs):
retrun Response('我是未登录用户')
2.局部使用
在需要使用的类中加入AnonRateThrottle 模块
from rest_framework.throttling import AnonRateThrottle
class Testview(APIView):
throttle_classes = [AnonRateThrottle]
2.2、内置频率限制登录用户访问频率
需求:将未登录用户1分钟访问5次,登录用户1分钟访问10次
全局:在setting中:
'DEFAULT_THROTTLE_CLASSES': (
‘rest_framework.throttling.AnnoRateThrottle’,
'rest_framework.throtting.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'user': '10/m',
'anon': '5/m',
}
局部:
在需要使用并且已经登录认证的类中加入AnonRateThrottle 模块
from rest_framework.throttling import AnonRateThrottle
class Testview(APIView):
throttle_classes = [AnonRateThrottle]
3、过滤
过滤功能是可以单独使用的,单独建立一个路径,填写数据对数据库进行查找
需要安装:pip3 install django-filter
注册:在setting中添加:'django-filter'
配置:在全局或者局部进行配置
'DEFAULT_FILTER_BACKENDS':('django_filter.rest_framework.DjangoFilterBakend')
视图类中:
添加字段,可以按照那个字段进行筛选
from rest_framework.generics import ListAPIView
from app01.models import Book
from app01.ser import BookSerializer
class BookView(ListAPIview)
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_fields = ('name','age',)
4、排序
排序需要导入OrderingFilter模块,可以和过滤一起使用
在全局中的设置和过滤功能是一致的,排序可以单独使用也可以和过滤一起使用。区别在于过滤使用的是filter_fields属性而排序使用的是ordering_fields属性,当二者合一的时候使用的是ordering属性,并且需要在filter_backends属性里面放置Djangofilterbackend,表示,先排序后过滤
from rest_framework.generics import ListAPIView
from rest_framework.filters import OrderingFilter
from app01.models import Book
from app01.ser import Bookserializer
class Bookview(ListAPIView):
queryset = Book.objects.all()
serializer_class = Bookserializer
filter_backends = [OrderingFiter]
ordering_fields = ('id','price')
排序和过滤结合使用,需要更改为:
filter_backends = [orderingFilter,Djangofilterbackend]
urls.py
url('book/',views.Bookview.as_view())
路径的使用:
http://127.0.0.1:8000/books2/?ordering=-price #倒序
http://127.0.0.1:8000/books2/?ordering=price
http://127.0.0.1:8000/books2/?ordering=-id
5、异常处理
异常处理是通过统一接口的返回,自己编写一个方法,自定义异常处理
异常分两种情况:第一种是none,drf没有处理,使用response捕捉,无响应
第二种是response对象,django处理了,但是不符合我们的要求,使用isinstance处理,数据库数据异常
fom rest_framework.views import exception_handlr
def my_exception_hendler(exc,context):
response = exception_handler(exc,context)
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(data={'status':888,'msg':response.data.get('detail')},status=status.HTTP_400_BAD_REQUEST)
全局设置setting
'EXCEPTION_HANDLER': 'app01.app_auth.my_exception_handler',
6、封装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,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={})