首页 > 编程语言 > 详细

drf权限,频率,过滤,排序,异常处理

时间:2020-07-10 21:08:28      阅读:81      评论:0      收藏:0      [点我收藏+]

一、权限

1 权限源码分析

# APIView---->dispatch----> self.initial(request, *args, **kwargs)
# ---->self.check_permissions(request)---->
 def check_permissions(self, request):
        # get_permissions是apiview的一个方法,得到的是一个列表
        # 这个列表的生成和认证一模一样,列表生成式内的可迭代对象是在apisettings里配置的
        # 这里我们就可以知道,权限的全局配置,局部配置应该和认证是一模一样的
        # 所以这里循环的列表是一个个权限校验类实例化得到的对象
        for permission in self.get_permissions():
            # 权限校验对象的核心是has_permission方法,返回值必须是bool
            # 这个方法接受了三个参数,权限对象,request,视图类对象
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request, message=getattr(permission, ‘message‘, None)
                )

2 自定义权限类

# uitl
class UserPermission(BasePermission):
    def has_permission(self,request,view):
        # 权限需要根据request.user判断,所以通常会和认证一起使用
        if request.user.user_type == 1:
            return True
        return False
    
# view
class StudentAPI(ModelViewSet):
    authentication_classes = [uitl.TokenAuthentication]
    permission_classes = [uitl.UserPermission]
    queryset = models.Student.objects
    serializer_class = StudentModelSerializer
    
# 局部使用
class TestView(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 = []

3 内置权限类

from rest_framework.permissions import IsAdminUser
from rest_framework.authentication import SessionAuthentication
class TestView3(APIView):
    # 如果要用内置的,就要用全套的内置,不容易出错
    authentication_classes=[SessionAuthentication,]
    # 判断用户是否是职员,is_stuff
    permission_classes = [IsAdminUser]
    def get(self,request,*args,**kwargs):
        return Response(‘这是22222222测试数据,超级管理员可以看‘)

二、频率

1 内置频率设置

# 全局设置
REST_FRAMEWORK = {
    ‘DEFAULT_THROTTLE_CLASSES‘: (
        # 未登陆
        ‘rest_framework.throttling.AnonRateThrottle‘,
        # 已登录,由于是内置的,所以若要使用权限和认证也要使用内置的
        ‘rest_framework.throttling.UserRateThrottle‘
    ),
    ‘DEFAULT_THROTTLE_RATES‘: {
        # 已登录 一分钟10次
        ‘user‘: ‘10/m‘,
        # 未登录 一分钟5次
        ‘anon‘: ‘5/m‘,
    }
}

# 局部配置
class StudentAPI(ModelViewSet):
    throttle_classes = [AnonRateThrottle]
    queryset = models.Student.objects
    serializer_class = StudentModelSerializer
# 这里只设置的频率类,没设置参数,参数只能在全局配置
REST_FRAMEWORK = {
    ‘DEFAULT_THROTTLE_RATES‘: {
        # 未登录 一分钟5次
        ‘anon‘: ‘5/m‘,
    }
}

三、过滤

# 安装django-filters
# 在settings注册django-filters
# 在settings配置
REST_FRAMEWORK = {
   ‘DEFAULT_FILTER_BACKENDS‘: (‘django_filters.rest_framework.DjangoFilterBackend‘,)

}
# 在视图类中定义可以过滤的字段
class StudentAPI(ModelViewSet):
	# 这里定义了name
    # 那么就可以在url后面用?拼接筛选条件
    # http://127.0.0.1:8000/student/?nanme=hz&id>1
    filter_fields = (‘name‘,‘id‘)
    filter_backends =[DjangoFilterBackend]
    queryset = models.Student.objects
    serializer_class = StudentModelSerializer

四、排序

from rest_framework.filters import OrderingFilter
class StudentAPI(ModelViewSet):	
    # 局部配置内置的排序类
    filter_backends = [OrderingFilter]
    # 限定可排序字段
	ordering_fields = (‘id‘, ‘price‘)
    
    # 按照id倒序,符号为倒序
    http://127.0.0.1:8000/student/?ordering=-id

总结:排序和过滤在局部配置和全局配置都放在一个列表里,只是配置的时候都要加一个限定字段列表,两者可以连用

五、异常处理

# 在drf的settings中
‘EXCEPTION_HANDLER‘: ‘rest_framework.views.exception_handler‘,
# 这表示drf的异常捕获配置方法
def exception_handler(exc, context):
    if isinstance(exc, Http404):
        exc = exceptions.NotFound()
    elif isinstance(exc, PermissionDenied):
        exc = exceptions.PermissionDenied()
    if isinstance(exc, exceptions.APIException):
        headers = {}
        if getattr(exc, ‘auth_header‘, None):
            headers[‘WWW-Authenticate‘] = exc.auth_header
        if getattr(exc, ‘wait‘, None):
            headers[‘Retry-After‘] = ‘%d‘ % exc.wait
        if isinstance(exc.detail, (list, dict)):
            data = exc.detail
        else:
            data = {‘detail‘: exc.detail}
        set_rollback()
        return Response(data, status=exc.status_code, headers=headers)
    return None
# 从上面的源码我们可以读取到几个信息
# 1 drf并没有把所有的异常捕获完,因为最后return None表示没有被drf捕获的异常会被django来捕获
# 2 异常是通过apisettings来配置的,也就是我们可以根据这个方法重写捕获异常

# 全局捕获异常
# 现在项目settings中配置

# 我们要在drf捕获异常的基础上再添加捕获,捕获应当有固定的返回信息
from rest_framework.response import Response
from rest_framework.views import exception_handler
def catch_all_exe(exc, context):
    respone = exception_handler(exc, context)
    if not respone:
        return Response(data={‘code‘:404,‘msg‘:f‘drf捕获的异常{str(exc)}‘},status=404)
    return Response(data={‘code‘:405,‘msg‘:f‘django捕获的异常{str(exc)}‘},status=405)

drf权限,频率,过滤,排序,异常处理

原文:https://www.cnblogs.com/hz2lxt/p/13280228.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!