一 过滤Filtering
SearchFilter:模糊匹配
Django-filter:精确匹配
1 内置过滤SearchFilter使用 1 2 3 4 5 6 7 from rest_framework.filters import SearchFilterclass BookView (ViewSetMixin,ListAPIView): filter_backends = [SearchFilter,] search_fields=['name' ,'publish' ]
2 django-filter过滤
对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持。
1 pip install django-filter
在配置文件中增加过滤后端的设置:
1 2 3 4 5 6 7 8 9 INSTALLED_APPS = [ ... 'django_filters' , ] REST_FRAMEWORK = { ... 'DEFAULT_FILTER_BACKENDS' : ('django_filters.rest_framework.DjangoFilterBackend' ,) }
在视图中添加filter_fields属性,指定可以过滤的字段
1 2 3 4 5 6 class StudentListView (ListAPIView ): queryset = Student.objects.all () serializer_class = StudentSerializer filter_fields = ('age' , 'sex' )
二 排序 对于列表数据,REST framework提供了OrderingFilter 过滤器来帮助我们快速指明数据按照指定字段进行排序。
使用方法:
在类视图中设置filter_backends,使用rest_framework.filters.OrderingFilter
过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。
前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。
示例:
1 2 3 4 5 6 7 8 9 class StudentListView (ListAPIView ): queryset = Student.objects.all () serializer_class = StudentModelSerializer filter_backends = [OrderingFilter] ordering_fields = ('id' , 'age' )
如果需要在过滤以后再次进行排序,则需要两者结合!
1 2 3 4 5 6 7 8 9 10 11 12 from rest_framework.generics import ListAPIViewfrom students.models import Studentfrom .serializers import StudentModelSerializerfrom django_filters.rest_framework import DjangoFilterBackendclass Student3ListView (ListAPIView ): queryset = Student.objects.all () serializer_class = StudentModelSerializer filter_fields = ('age' , 'sex' ) filter_backends = [OrderingFilter,DjangoFilterBackend] ordering_fields = ('id' , 'age' )
REST framework提供了分页的支持。
我们可以在配置文件中设置全局的分页方式,如:
1 2 3 4 REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS' : 'rest_framework.pagination.PageNumberPagination' , 'PAGE_SIZE' : 100 }
也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过pagination_clas
属性来指明。
1 2 3 4 5 6 7 8 class LargeResultsSetPagination (PageNumberPagination ): page_size = 1000 page_size_query_param = 'page_size' max_page_size = 10000 class BookDetailView (RetrieveAPIView ): queryset = BookInfo.objects.all () serializer_class = BookInfoSerializer pagination_class = LargeResultsSetPagination
注意:如果在视图内关闭分页功能,只需在视图内设置
可选分页器 1) PageNumberPagination
前端访问网址形式:
1 GET http:// 127.0 .0.1 :8000 /students/ ?page=4
可以在子类中定义的属性:
page_size 每页数目,必须指定,不然会报错
page_query_param 前端发送的页数关键字名,默认为”page”
page_size_query_param 前端发送的每页数目关键字名,默认为None
max_page_size 前端最多能设置的每页数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 from rest_framework.pagination import PageNumberPaginationclass Pager (APIView ): def get (self,request,*args,**kwargs ): ret=models.Book.objects.all () page=PageNumberPagination() page_list=page.paginate_queryset(ret,request,view=self) ser=BookSerializer1(instance=page_list,many=True ) return Response(ser.data) class Mypage (PageNumberPagination ): page_size = 2 page_query_param = 'page' page_size_query_param = 'size' max_page_size = 5 class Pager (APIView ): def get (self,request,*args,**kwargs ): ret=models.Book.objects.all () page=Mypage() page_list=page.paginate_queryset(ret,request,view=self) ser=BookSerializer1(instance=page_list,many=True ) return page.get_paginated_response(ser.data) from rest_framework.pagination import PageNumberPaginationclass StandardPageNumberPagination (PageNumberPagination ): page_size = 2 page_size_query_param = "size" max_page_size = 10 page_query_param = "p" class StudentAPIView (ListAPIView ): queryset = Student.objects.all () serializer_class = StudentModelSerializer pagination_class = StandardPageNumberPagination
2)LimitOffsetPagination
前端访问网址形式:
1 GET http:// 127.0 .0.1 /four/ students/?limit=100 &offset=400
可以在子类中定义的属性:
default_limit 默认限制,默认值与PAGE_SIZE
设置一直
limit_query_param limit参数名,默认’limit’
offset_query_param offset参数名,默认’offset’
max_limit 最大limit限制,默认None
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from rest_framework.pagination import LimitOffsetPaginationclass Pager (APIView ): def get (self,request,*args,**kwargs ): ret=models.Book.objects.all () page=LimitOffsetPagination() page_list=page.paginate_queryset(ret,request,view=self) ser=BookSerializer1(instance=page_list,many=True ) return Response(ser.data) from rest_framework.pagination import LimitOffsetPaginationclass StandardLimitOffsetPagination (LimitOffsetPagination ): default_limit = 2 limit_query_param = "size" offset_query_param = "start" class StudentAPIView (ListAPIView ): queryset = Student.objects.all () serializer_class = StudentModelSerializer pagination_class = StandardLimitOffsetPagination
3)CursorPagination
前端访问网址形式:
1 GET http:// 127.0 .0.1 /four/ students/?cursor=cD0xNQ%3 D%3 D
可以在子类中定义的属性:
cursor_query_param:默认查询字段,不需要修改
page_size:每页数目
ordering:按什么排序,需要指定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 from rest_framework.pagination import CursorPaginationclass Pager (APIView ): def get (self,request,*args,**kwargs ): ret=models.Book.objects.all () page=CursorPagination() page.ordering='nid' page_list=page.paginate_queryset(ret,request,view=self) ser=BookSerializer1(instance=page_list,many=True ) return page.get_paginated_response(ser.data) class MyCursorPagination (CursorPagination ): page_size=2 ordering='-id' from rest_framework.generics import ListAPIViewclass AuthorListView (ListAPIView ): serializer_class = serializers.AuthorModelSerializer queryset = models.Author.objects.filter (is_delete=False ) pagination_class =MyCursorPagination
应用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPaginationclass MyPageNumberPagination (PageNumberPagination ): page_size = 2 page_query_param = 'page' page_size_query_param = 'size' max_page_size = 5 class MyLimitOffsetPagination (LimitOffsetPagination ): default_limit = 2 max_limit = 5 class MyCursorPagination (CursorPagination ): page_size=2 ordering='-id' from rest_framework.generics import ListAPIViewclass AuthorListView (ListAPIView ): serializer_class = serializers.AuthorModelSerializer queryset = models.Author.objects.filter (is_delete=False ) pagination_class =MyCursorPagination
四 异常处理 Exceptions REST framework提供了异常处理,我们可以自定义异常处理函数。
4.1 使用方式 1 2 3 4 5 6 7 8 9 10 11 from rest_framework.views import exception_handlerdef custom_exception_handler (exc, context ): response = exception_handler(exc, context) if response is None : response.data['status_code' ] = response.status_code return response
在配置文件中声明自定义的异常处理
1 2 3 REST_FRAMEWORK = { 'EXCEPTION_HANDLER' : 'my_project.my_app.utils.custom_exception_handler' }
如果未声明,会采用默认的方式,如下
rest_frame/settings.py
1 2 3 REST_FRAMEWORK = { 'EXCEPTION_HANDLER' : 'rest_framework.views.exception_handler' }
4.2 案例 补充上处理关于数据库的异常
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 from rest_framework.views import exception_handlerfrom rest_framework.response import Responsefrom rest_framework.views import exception_handler as drf_exception_handlerfrom rest_framework import statusfrom django.db import DatabaseErrordef 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 REST_FRAMEWORK = { 'EXCEPTION_HANDLER' : 'app01.ser.exception_handler' }
4.3 REST framework定义的异常
APIException 所有异常的父类
ParseError 解析错误
AuthenticationFailed 认证失败
NotAuthenticated 尚未认证
PermissionDenied 权限决绝
NotFound 未找到
MethodNotAllowed 请求方式不支持
NotAcceptable 要获取的数据格式不支持
Throttled 超过限流次数
ValidationError 校验失败
也就是说,很多的没有在上面列出来的异常,就需要我们在自定义异常中自己处理了。