- 一 过滤Filtering
- 二 排序
- 三 分页Pagination
- APIView
- http://127.0.0.1:8000/pager/?page=2&size=3,size无效">一 基本使用:url=url=http://127.0.0.1:8000/pager/?page=2&size=3,size无效
- http://127.0.0.1:8000/pager/?page=2&size=3">二 自定制 url=http://127.0.0.1:8000/pager/?page=2&size=3
- size=30,无效,最多5条
- 定制传参
- 最大一页的数据
- ListAPIView
- 声明分页的配置类
- 127.0.0.1/four/students/?p=1&size=5
- APIView
- http://127.0.0.1:8000/pager/?offset=4&limit=3">http://127.0.0.1:8000/pager/?offset=4&limit=3
- 也可以自定制,同简单分页
- ListAPIView
- 默认每一页查询的数据量,类似上面的page_size
- 定制传参
- 最大一页的数据

一 过滤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 = StudentSerializerfilter_fields = ('age', 'sex')# 127.0.0.1:8000/four/students/?sex=1
二 排序
对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。
使用方法:
在类视图中设置filter_backends,使用rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。
前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。
示例:
class StudentListView(ListAPIView):queryset = Student.objects.all()serializer_class = StudentModelSerializerfilter_backends = [OrderingFilter]ordering_fields = ('id', 'age')# 127.0.0.1:8000/books/?ordering=-age# -id 表示针对id字段进行倒序排序# id 表示针对id字段进行升序排序
如果需要在过滤以后再次进行排序,则需要两者结合!
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 = StudentModelSerializerfilter_fields = ('age', 'sex')# 因为局部配置会覆盖全局配置,所以需要重新把过滤组件核心类再次声明,# 否则过滤功能会失效filter_backends = [OrderingFilter,DjangoFilterBackend]ordering_fields = ('id', 'age')
三 分页Pagination
REST framework提供了分页的支持。
我们可以在配置文件中设置全局的分页方式,如:
REST_FRAMEWORK = {'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination','PAGE_SIZE': 100 # 每页数目}
也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过pagination_clas属性来指明。
class LargeResultsSetPagination(PageNumberPagination):page_size = 1000page_size_query_param = 'page_size'max_page_size = 10000class BookDetailView(RetrieveAPIView):queryset = BookInfo.objects.all()serializer_class = BookInfoSerializerpagination_class = LargeResultsSetPagination
注意:如果在视图内关闭分页功能,只需在视图内设置
pagination_class = None
可选分页器
1) PageNumberPagination
前端访问网址形式:
GET http://127.0.0.1:8000/students/?page=4
可以在子类中定义的属性:
- page_size 每页数目
- page_query_param 前端发送的页数关键字名,默认为”page”
- page_size_query_param 前端发送的每页数目关键字名,默认为None
- max_page_size 前端最多能设置的每页数量
```python
APIView
from rest_framework.pagination import PageNumberPagination一 基本使用:url=url=http://127.0.0.1:8000/pager/?page=2&size=3,size无效
class 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)
二 自定制 url=http://127.0.0.1:8000/pager/?page=2&size=3
size=30,无效,最多5条
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 Response(ser.data)# 这个也是返回Response对象,但是比基本的多了上一页,下一页,和总数据条数(了解即可)return page.get_paginated_response(ser.data)
ListAPIView
声明分页的配置类
from rest_framework.pagination import PageNumberPagination class StandardPageNumberPagination(PageNumberPagination):
# 默认每一页显示的数据量page_size = 2# 允许客户端通过get参数来控制每一页的数据量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
127.0.0.1/four/students/?p=1&size=5
<a name="4kL6h"></a>### 2)LimitOffsetPagination前端访问网址形式:```pythonGET 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
```python
APIView
http://127.0.0.1:8000/pager/?offset=4&limit=3
from rest_framework.pagination import LimitOffsetPagination也可以自定制,同简单分页
class 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 page.get_paginated_response(ser.data)return Response(ser.data)
ListAPIView
from rest_framework.pagination import LimitOffsetPagination class StandardLimitOffsetPagination(LimitOffsetPagination):默认每一页查询的数据量,类似上面的page_size
default_limit = 2 limit_query_param = “size” offset_query_param = “start”
class StudentAPIView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer
# 调用页码分页类# pagination_class = StandardPageNumberPagination# 调用查询偏移分页类pagination_class = StandardLimitOffsetPagination
<a name="sTDTm"></a>### 3)CursorPagination前端访问网址形式:```pythonGET http://127.0.0.1/four/students/?cursor=cD0xNQ%3D%3D
可以在子类中定义的属性:
- cursor_query_param:默认查询字段,不需要修改
- page_size:每页数目
- ordering:按什么排序,需要指定
#APIViewfrom rest_framework.pagination import CursorPagination# 看源码,是通过sql查询,大于id和小于idclass 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)# ListAPIViewclass MyCursorPagination(CursorPagination):page_size=2ordering='-id'from rest_framework.generics import ListAPIViewclass AuthorListView(ListAPIView):serializer_class = serializers.AuthorModelSerializerqueryset = models.Author.objects.filter(is_delete=False)pagination_class =MyCursorPagination
应用
```python from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination class 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 ListAPIView class AuthorListView(ListAPIView): serializer_class = serializers.AuthorModelSerializer queryset = models.Author.objects.filter(is_delete=False) pagination_class =MyCursorPagination
<a name="6e930407"></a># 四 异常处理 ExceptionsREST framework提供了异常处理,我们可以自定义异常处理函数。<a name="d210df44"></a>## 4.1 使用方式```pythonfrom rest_framework.views import exception_handlerdef custom_exception_handler(exc, context):# 先调用REST framework默认的异常处理方法获得标准错误响应对象response = exception_handler(exc, context)# 在此处补充自定义的异常处理if response is None:response.data['status_code'] = response.status_codereturn response
在配置文件中声明自定义的异常处理
REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'}
如果未声明,会采用默认的方式,如下
rest_frame/settings.py
REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'}
4.2 案例
补充上处理关于数据库的异常
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# 在setting.py中配置REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'app01.ser.exception_handler'}
4.3 REST framework定义的异常
- APIException 所有异常的父类
- ParseError 解析错误
- AuthenticationFailed 认证失败
- NotAuthenticated 尚未认证
- PermissionDenied 权限决绝
- NotFound 未找到
- MethodNotAllowed 请求方式不支持
- NotAcceptable 要获取的数据格式不支持
- Throttled 超过限流次数
- ValidationError 校验失败
也就是说,很多的没有在上面列出来的异常,就需要我们在自定义异常中自己处理了。
