排序和过滤
导入排序和过滤模块
from rest_framework.filters import SearchFilter, OrderingFilter
在视图类里面添加类属性
方式一:(内置的)
内置的过滤组件只支持search模糊匹配。不支持精准匹配。
举例http://127.0.0.1:8000/publish/?search=上, 在URL地址中的过滤字段。
filter_backends = [SearchFilter, OrderingFilter]
search_fields = ['name', 'addr']
order_fields = ['id']
方式二:(第三方)
方式二,借助第三方模块。
精准匹配--->Django.filter
pip3 install django-filter
基本方法跟方法一一样。
首先导入模块from django_filters.rest_framework import DjangoFilterBackend
设置类属性filter_backends = [DjangoFilterBackend]和filtersets_fields = ['name']
在URL地址中搜索:name=
你的过滤条件是什么就搜索什么。
方式三:(自定义)
有的时候,内置组件和第三方组件可能都没有办法满足我们的需求或者不完美,这个时候需要我们自定义,自己来写一个过滤器。
'''
1. 先创建一个filter.py文件专门用来写自定义的过滤器
2. 导入模块,继承模块,重写方法
'''
from rest_framework.filters import BaseFilterBackend
class PublishFilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
# 基于query_set进行过滤,过滤后返回即可
# http://127.0.0.1:8000/publish/?addr=北京市 名字有它的直接查出来
search_params = request.query_params.get('name')
if search_params:
queryset = queryset.filter(name__contains=search_params)
return queryset
添加或者筛选条件,导入from django.db.models import Q
回到视图层直接设置filter_backends = [PublishFilter] 就好
继承APIView写过滤类
继承GenericAPIView写过滤类
写多个过滤类时,它们的执行过滤顺序是从左往右, 依次执行的。大原则,配置多个过滤类时候,第一个尽量放过滤越多的过滤类。
分页
针对 查询的所有接口
展现形式: Web 下一页,下一页 APP 下拉 下拉
必须继承GenericAPIView
第一种方法
导入from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
class CommonPageNumberPagination(PageNumberPagination):
'''
http://api.example.org/accounts/?page=4
http://api.example.org/accounts/?page=4&page_size=100
'''
# 重写几个类属性
page_size = 2 # --->每页显示几条数据
page_query_param = 'page' # --->指定页数的Key
page_size_query_param = 'size' # --->可以指定每页显示多少条
max_page_size = 5 # --->每页最多显示多少条
视图层里面只需要添加这个类pagination_class = CommonPageNumberPagination
切记,这个不能以列表的形式添加,否则会报错。
结果展示:
{
"count": 11,
"next": "http://127.0.0.1:8000/book/?page=4",
"previous": "http://127.0.0.1:8000/book/?page=2",
"results": [
{
"id": 5,
"title": "三字经",
"price": "8.8",
"is_delete": 0,
"publish": 2,
"author": []
},
{
"id": 6,
"title": "道德经",
"price": "55",
"is_delete": 0,
"publish": 2,
"author": []
}
]
}
第二种方法
定义类,重写属性
class CommonLimitOffsetPagination(LimitOffsetPagination):
'''
http://api.example.org/accounts/?limit=100 从开始取100条
http://api.example.org/accounts/?offset=400&limit=100 从第400条开始取后面100条
'''
# 重新写几个属性
default_limit = 3 # ---> 默认每页显示多少条
limit_query_param = 'limit' # --->每页显示多少条的查询条件
offset_query_param = 'offset' # --->
max_limit = 5 # --->限制最多取5条
第三种方法(主要用于APP应用)
高效率
class CommonCursorPagination(CursorPagination):
# 只能上一页和下一页,不能指定跳转到中间的某页,效率高,大数据量的时候用它
cursor_query_param = 'cursor' # 查询条件
page_size = 2 # 每页显示两条
ordering = 'id' # 按照id排序,这个必须是表中字段
异常处理
三大认证中的异常
三大认证,视图类的方法中执行出错,都会被全局异常捕获
-认证类,认证不通过,抛异常,前端没有看到问题,只是返回了提示信息--->处理了DRF的额异常
DRF全局异常处理,它只会把DRF的异常处理掉,统一返回个是,但是Django原生的异常和Python的异常都不胡处理。
而我们要做的就是统一化所有异常。
exceptions.py
'''
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
'''
from rest_framework.views import exception_handler
from rest_framework.response import Response
def common_exceptions(exc, context):
# 如果DRF的异常捕捉能处理,我们就不用处理了
res = exception_handler(exc, context)
if not res:
return Response({'code':8888, 'msg':'❌非DRF程序错误---%s'%str(exc)})
else:
return Response({'code':8888, 'msg':f'❌DRF错误---{res.data.get("detail")}'})
settings.py
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'app01.exceptions.common_exceptions'
}