九、过滤_排序_异常处理_封装Response

过滤

一、过滤器下载

pip3 install django-filter

二、过滤器配置

# 注册
INSTALLED_APPS = [
    'django_filters',	# 注册
]

# 全局配置-settings.py
REST_FRAMEWORK = {
    ...
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
}

# 局部配置,在视图函数中
DEFAULT_FILTER_BACKENDS = ['django_filters.rest_framework.DjangoFilterBackend']

# 局部禁用,在视图函数中
DEFAULT_FILTER_BACKENDS = []

三、过滤器使用

from rest_framework.generics import ListAPIView

class xxx(ListAPIView):
    queryset = 模型表对象
    # queryset = models.表名.objects
    
    serializer_class = 模型表对象
    # serializer_class = ZzwSerializer
    
    filter_fields = ('字段名',...)
    # 写入模型表中,使用什么字段进行过滤

排序

一、排序

from rest_framework.filters import OrderingFilter

二、排序配置

# 全局配置-settings.py
REST_FRAMEWORK = {
    ...
    'DEFAULT_FILTER_BACKENDS': [
        # 过滤组件
        'django_filters.rest_framework.DjangoFilterBackend',
        # 排序组件
        'rest_framework.filters.OrderingFilter',
    ],
}

# 局部配置,在视图函数中
DEFAULT_FILTER_BACKENDS = [
    # 过滤组件
    'django_filters.rest_framework.DjangoFilterBackend',
    # 排序组件
    'rest_framework.filters.OrderingFilter',
]

# 局部禁用,在视图函数中
DEFAULT_FILTER_BACKENDS = []

三、排序使用

from rest_framework.generics import ListAPIView

class xxx(ListAPIView):
    queryset = 模型表对象
    # queryset = models.表名.objects
    
    serializer_class = 模型表对象
    # serializer_class = ZzwSerializer
    
    filter_fields = ('字段名',...)
    # 写入模型表中,使用什么字段进行过滤
    
    ordering_fields = ('字段名', ...)
    # 写入模型表中,使用什么字段进行排序

异常处理

一、(APIView)dispatch

'''
在观察了父类View的as_view方法后,我们发现其内部最终是调用dispatch方法(关键)

对于当前类,最近的dispatch方法,即是APIView中的dispatch方法,我们进行下一步研究:
	1. 加工原生request
	2. 增添三大认证模块
	3. 利用反射调用请求方法的对应方法
	4. 使用异常模块收集异常
	5. 利用渲染模块,渲染最终数据
'''
    def dispatch(self, request, *args, **kwargs):
        
        # 对当前接收参数使用对象属性存储
        self.args = args
        self.kwargs = kwargs
        
        # 将原生request,传入至initialize_request方法,进行加工后,返回加工后的request
        request = self.initialize_request(request, *args, **kwargs)

        # 此刻对象属性request存储的为加工后的reqeust
        self.request = request
        
        self.headers = self.default_response_headers  # deprecate?

        try:
            # 该方法内部包含三大认证模块
            self.initial(request, *args, **kwargs)
			
            
            '''
            反射:
            	1. 获取当前对象中的对应方法(get、post、put、patch、delete....)
           		2. 调用方法,并传入参数
           	
           	判断当前请求方式,是否存在于http_method_names属性中的方式
           	http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
           	
           	如果存在,则调用对象中的对应方法,否则使用默认方法http_method_not_allowed
            '''
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
                
                
			# 响应模块:执行对应方法,并传入 加工后的request参数
            response = handler(request, *args, **kwargs)
		
        
        except Exception as exc:
            # 异常模块:如果出现异常,则调用异常方法,返回对应的异常信息,而不是前端直接报错
            response = self.handle_exception(exc)
		
        # 渲染模块:将数据进行加工后,返还给前端精美的页面
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response

二、全局异常源码

from rest_framework.views import exception_handler

def exception_handler(exc, context):
    
    # 判断异常对象是否为 Http404 异常
    if isinstance(exc, Http404):
        # exc = 404 异常
        exc = exceptions.NotFound()
    
    # 判断异常对象是否为 PermissionDenied 异常
    elif isinstance(exc, PermissionDenied):
        # exc = 403 异常
        exc = exceptions.PermissionDenied()
	
    # 判断异常对象是否为 APIException 异常
    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)
	
    # 对于其他异常,不进行处理,直接交给django处理
    return None



# 抛出 404 异常
class NotFound(APIException):
    status_code = status.HTTP_404_NOT_FOUND
    default_detail = _('Not found.')
    default_code = 'not_found'
    
# 抛出 403 异常    
class PermissionDenied(APIException):
    status_code = status.HTTP_403_FORBIDDEN
    default_detail = _('You do not have permission to perform this action.')
    default_code = 'permission_denied'

# 抛出 500 异常
class APIException(Exception):
    status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
    default_detail = _('A server error occurred.')
    default_code = 'error'
    ...

三、自定义异常处理

from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status


# 在app下创建任意名称的py文件,书写以下模板
def Zzw_exception_handler(exc, context):
    # 原来rest_framework的异常类,我们依然使用,只是在其基础上扩展
    response = exception_handler(exc, context)
    '''
    response有两种情况:
    	返回Response,处理了异常,但并不完整
    	返沪None,没有处理异常
    '''
    if not response:
        errors = {
            'status': 1000,
            'msg': str(exc),
        }
    else:
        errors = {
            'status': 2000,
            'msg': request.data.get('detail'),
        }
    return Response(data=errors, status=status.HTTP_400_BAD_REQUEST)

四、配置异常处理

# 全局配置-settings.py
REST_FRAMEWORK = {
    ...,
    # rest_framework默认配置的异常处理类
	'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
    # 我们需要写入自己定义的,所以修改上面的代码如下
    'EXCEPTION_HANDLER': 'app01.自己定义的异常类路径',
}

封装response(重要)

from rest_framework.response import Response


class APIResponse(Response):
    def __init__(self, code=100, msg='成功', data=None, status=None, headers=None, content_type=None, **kwargs):
        data = {'code': code, 'msg': msg,}
        
        # 判断data是否有值
        if data:
        	data['data'] = data
        
        # 可以增加额外参数
        data.update(**kwargs)
        
        super.__init__(data=data, status=status, headers=headers, content_type=content_type)

 

上一篇:sys模块


下一篇:python各种包安装bug汇总