一 过滤Filtering
对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持。
安装
pip install django-filter 注册 INSTALLED_APPS = [ ... 'django_filters', # 需要注册应用, ]
全局配置
REST_FRAMEWORK = { ... 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) } # 在视图中添加filter_fields属性,指定可以过滤的字段 class StudentListView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentSerializer filter_fields = ('age', 'sex') # 127.0.0.1:8000/four/students/?sex=1
局部配置
from django_filters.rest_framework import DjangoFilterBackend class StudentListView(ListAPIView): ... filter_backends = [DjangoFilterBackend,] filter_fields = ('age', 'sex')
二 排序
对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。
使用方法:
在类视图中设置filter_backends,使用rest_framework.filters.OrderingFilter
过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。
前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。
示例:
from rest_framework.generics import ListAPIView from rest_framework.filters import OrderingFilter from app01.models import Book from app01.ser import BookSerializer class Book2View(ListAPIView): queryset = Book.objects.all() serializer_class = BookSerializer 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 http://127.0.0.1:8000/books2/?ordering=-id -id 表示针对id字段进行倒序排序 id 表示针对id字段进行升序排序
如果需要在过滤以后再次进行排序,则需要两者结合!
from django_filters.rest_framework import DjangoFilterBackend class Book2View(ListAPIView): queryset = Book.objects.all() serializer_class = BookSerializer filter_fields = ('id', 'price') # 过滤 # 因为局部配置会覆盖全局配置,所以需要重新把过滤组件核心类再次声明, # 否则过滤功能会失效 filter_backends = [OrderingFilter,DjangoFilterBackend] # 过滤要写在排序之后 ordering_fields = ('id', 'prcie') #排序
三 异常处理 Exceptions
REST framework提供了异常处理,我们可以自定义异常处理函数。
3.1 使用方式
from rest_framework.views import exception_handler def my_exception_handler(exc, context): # 先调用REST framework默认的异常处理方法获得标准错误响应对象 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)
在配置文件中声明自定义的异常处理
REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'app01.app_auth.my_exception_handler', }
3.2 案例
补充上处理关于数据库的异常
from rest_framework.views import exception_handler from rest_framework.response import Response from rest_framework.views import exception_handler as drf_exception_handler from rest_framework import status from django.db import DatabaseError def exception_handler(exc, context): response = drf_exception_handler(exc, context) if response is None: view = context['view'] print('[%s]: %s' % (view, exc)) if isinstance(exc, DatabaseError): response = Response({'detail': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE) else: response = Response({'detail': '未知错误'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) return response # 在setting.py中配置 REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'app01.ser.exception_handler' }
3.3 REST framework定义的异常
- APIException 所有异常的父类
- ParseError 解析错误
- AuthenticationFailed 认证失败
- NotAuthenticated 尚未认证
- PermissionDenied 权限决绝
- NotFound 未找到
- MethodNotAllowed 请求方式不支持
- NotAcceptable 要获取的数据格式不支持
- Throttled 超过限流次数
- ValidationError 校验失败
也就是说,很多的没有在上面列出来的异常,就需要我们在自定义异常中自己处理了。
四 封装Response对象(重要)
为了让放回的数据有一定的格式我们要使用自己封装的Response对象
from rest_framework.response import 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={})