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)