drf过滤排序异常封装Response

过滤&排序

过滤排序的使用一定要基于继承了GenericAPIView和调用了GenericAPIView.filter_queryset方法的类。

安装三方组件

# 安装
pip3 install django-filter

# 注册
在项目配置文件中注册django-filter这个app(不注册在浏览器中使用会报错)

过滤

过滤使用的是django-filter的DjangoFilterBackend

#3 全局配置
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend', # 过滤配置
    ),
}
#4 视图类
class BookView(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_fields = ('name', 'price', 'publish')  		# 配置过滤字段,可以多个同时使用
# 局部配置(需要先导入)
from rest_framework.filters import OrderingFilter
class Book2View(ListAPIView):
    filter_backends = [DjangoFilterBackend]
    ordering_fields = ('id', 'price')


# 使用
http://127.0.0.1:8000/books2/?name=book1
http://127.0.0.1:8000/books2/?price=12.12
http://127.0.0.1:8000/books2/?publish=1&price=12.12

排序

排序使用的是drf的OrderingFilter

# 全局使用
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': (
        'rest_framework.OrderingFilter',	 # 排序配置
    )
}
class Book2View(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    ordering_fields = ('id', 'price')		# 排序配置


# 局部使用
from rest_framework.filters import OrderingFilter
class Book2View(ListAPIView):
    filter_backends = [OrderingFilter]
    ordering_fields = ('id', 'price')


# 使用:
http://127.0.0.1:8000/books2/?ordering=-price		# 逆序 -
http://127.0.0.1:8000/books2/?ordering=price

同时使用过滤和排序的配置

# 全局配置
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend', 	# 过滤配置
        'rest_framework.filters.OrderingFilter',					# 排序配置
    ),
}

# 局部配置
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import OrderingFilter
filter_backends = [DjangoFilterBackend,OrderingFilter]

过滤排序使用总结

# 排序:
按id正序倒叙排序,按price正序倒叙排列
使用:http://127.0.0.1:8000/course/free/?ordering=-id
配置类:
    filter_backends=[OrderingFilter]
配置字段:
    ordering_fields=['id','price']
    
    
# 内置过滤:
使用:http://127.0.0.1:8000/course/free/?search=39
按照price过滤(表自有的字段直接过滤)
配置类:
    filter_backends=[SearchFilter]
配置字段:
    search_fields=['price']
  

# 扩展:django-filter
安装:
支持自由字段的过滤还支持外键字段的过滤
http://127.0.0.1:8000/course/free/?course_category=1   # 过滤分类为1 (python的所有课程)
配置类:
    filter_backends=[DjangoFilterBackend]
配置字段:
    filter_fields=['course_category']

异常处理

drf内置的异常捕获处理的异常有三类:

Subclasses of APIException raised inside REST framework.
Django's Http404 exception.
Django's PermissionDenied exception.
# 统一接口返回

# 自定义异常方法,替换掉全局
# 写一个方法
# 自定义异常处理的方法
from rest_framework.views import exception_handler
from .response import APIResponse
from .logger import log


def common_exception_handler(exc, context):
    # 记录异常日志
    log.error('view是:%s ,错误是%s' % (context['view'].__class__.__name__, str(exc)))
    # 先调用内置异常捕获方法,获取标准烦人异常返回对象
    ret = exception_handler(exc, context)

    if not ret:
         # drf未处理的异常,我们自己再做处理
        if isinstance(exc, KeyError):
            return APIResponse(code=0, msg='key error')

        return APIResponse(code=0, msg='error', result=str(exc))
    else:
        return APIResponse(code=0, msg='error', result=ret.data)

# 全局配置setting.py
REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'            # 配置导入自定义异常的路径
}

封装Response对象(重要)

# 以后都用自己封装的,核心是替换掉Response的data, 并保留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={})

drf封装好的内置视图,内部的返回的是默认的Response()对象,如果需要在这个对象上面封装一层自己的格式,这是一个解决思路是调用父类的封装方法,得到返回值(就是Response对象),然后再在这个基础上封装自己的返回格式。

class BookAPIView(RetrieveUpdateDestroyAPIView):

    queryset = models.Book.objects.all()
    serializer_class = ser.BookSerializer

    def get(self, request, *args, **kwargs):
        response = super().get(request, *args, **kwargs)
        return utils.APIResponse(data=response.data)

    def delete(self, request, *args, **kwargs):
        response = super().delete(request, *args, **kwargs)
        return utils.APIResponse(data=response.data, msg='删除成功')

    def put(self, request, *args, **kwargs):
        response = super().put(request, *args, **kwargs)
        return utils.APIResponse(data=response.data)
posted @ 2020-07-11 13:27  the3times  阅读(266)  评论(0编辑  收藏  举报