过滤和排序
内置
# 查询所有才需要过滤(根据条件过滤),排序(按某个规则排序)
# 内置过滤类使用,在视图类中配置
from rest_framework.filters import SearchFilter
class BookView(ViewSetMixin,ListAPIView):
# 在视图类中配置,最顶层的类至少是GenericAPIView
filter_backends = [SearchFilter,]
# 过滤条件,按名字过滤
search_fields=['name','publish']
# 查询
http://127.0.0.1:8000/books/?search=达 # 出版社中或名字中有'达'就能查询出来
## 内置排序类(既有排序,又有过滤)
from rest_framework.filters import OrderingFilter,SearchFilter
class BookView(ViewSetMixin,ListAPIView):
# 在视图类中配置,最顶层的类至少是GenericAPIView
filter_backends = [SearchFilter,OrderingFilter,]
# 过滤条件,按名字过滤
search_fields=['name']
# 按哪个字段排序
ordering_fields=['price','id']
# 排序
http://127.0.0.1:8000/books/?ordering=price,-id
第三方
# 第三方pip3 install django-filter
# 视图类中
from django_filters.rest_framework import DjangoFilterBackend
class BookView(ViewSetMixin,ListAPIView):
# 在视图类中配置,最顶层的类至少是GenericAPIView
filter_backends = [DjangoFilterBackend,]
# 按名字过滤
filter_fields=['name','price']
# 查询时
http://127.0.0.1:8000/books/?name=红楼梦
http://127.0.0.1:8000/books/?name=四方达&price=15
# filter_backends的列表中可以写多个方法,使用时会按顺序进行,将前一个的结果交给后一个处理
自定义
分页
- 只有查询所有的接口才使用分页功能,网页中的下一页,app的下滑加载更多
- 使用:
- 先新建一个pagination.py文件,写一个类,继承对应的分页类,重写几个类属性
- 在视图类中卑职分页类即可,类属性pagination_class=自己写的类
- 配置分页类需要继承GenericAPIView及子类,才能使用。
基本分页
from rest_framework.pagination import PageNumberPagination
class CommonPageNumberPagination(PageNumberPagination):
page_size = 2 # 每页的条数
page_query_param = 'page' # 查询时用的参数
# http://127.0.0.1:8000/books/?page=2
page_size_query_param = 'size' # 通过这个参数更改返回的条数
# 第一页返回四条 http://127.0.0.1:8000/books/?page=1&size=4
max_page_size = None # 更改一页最多显示的条数
class BookView(ViewSetMixin, ListAPIView):
pagination_class = CommonPageNumberPagination
偏移分页
from rest_framework.pagination import LimitOffsetPagination
class CommonLimitOffsetPagination(LimitOffsetPagination):
default_limit = 2 # 显示多少条
limit_query_param = 'limit' # limit的参数
offset_query_param = 'offset' # offset偏移的查询参数
max_limit = 5 # 最大显示条数,为5
class BookView(ViewSetMixin, ListAPIView):
pagination_class = LimitOffsetPagination
# 在offset位置,向后查看limit条数据
# http://127.0.0.1:8000/book/?limit=3&offset=5 ,查看6开始的3条数据
游标分页
from rest_framework.pagination import CursorPagination
class CommonCursorPagination(CursorPagination):
page_size = 3 # 每页显示多少条
cursor_query_param = 'cursor' # 查询条件
ordering = 'id' # 排序,按id排序
page_size_query_param = 'size' # 通过这个参数决定每页显示多少条
max_page_size = 5 # 每页最大显示多少条
class BookView(ViewSetMixin, ListAPIView):
pagination_class = CommonCursorPagination
http://127.0.0.1/four/students/?cursor=cD0xNQ%3D%3D
# 类似于将页码加密,只能通过上一页下一页来进行翻页
# 优点:速度最快,数据量越大越有优势
# 缺点:只能上一页下一页,不能跳到指定某一页
继承APIView实现分页
class BookViewALL(APIView):
def get(self,request,*args,**kwargs):
book_list=Books.objects.all()
#实例化得到一个对象
pagination=CommonPageNumberPagination()
# 修改对象属性,我们继承了自己定义的类,这里不需要改
# pagination.page_query_param='page'
#调用对象方法,传入要分页的数据,book_list,返回分页号的数据
book_list2=pagination.paginate_queryset(book_list,request,self)
ser=BookSerializer(instance=book_list2,many=True)
res={'pre':pagination.get_previous_link(),'next':pagination.get_next_link(),'count':pagination.page.paginator.count,'data':ser.data}
return Response(res)
# 另一种返回方式
return pagination.get_paginated_response(ser.data)
异常处理
1 全局统一捕获异常,返回固定的格式 {code:999,msg:'未知错误'}
2 使用步骤
-新建一个utils.py
-写一个函数(模仿默认的)
-在配置文件中配置
# 默认配置文件中:'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
# 写函数
from rest_framework.views import exception_handler
from rest_framework.response import Response
def common_exception_handler(exc, context):
# 记录日志,context中有view对象和request对象
print(context['request'].META.get('REMOTE_ADDR'))
response=exception_handler(exc, context)
if response: # 处理了drf的异常
data = {'code': 999, 'msg': '错误','detail':response.data}
else: # 不知道的异常
data = {'code':999,'msg':'未知错误'}
return Response(data)
# 配置文件配置
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'app01.utils.common_exception_handler',
}