过滤,分页,异常处理
1 过滤
只针对于 查询所有接口
必须继承 GenericAPIView
# 安装:
pip install django==3.2.12
pip install django-filter
# 使用方式:三种
-方式一:内置的
# 查询方式http://127.0.0.1:8000/books/?search=29 #模糊匹配: 只要名字中有29或价格中有29都能搜出来
# filter_backends = [SearchFilter, OrderingFilter]
# search_fields = ['name', 'price']
-方式二:第三方
# http://127.0.0.1:8000/books/?name=红楼梦
# http://127.0.0.1:8000/books/?price=19&name=西游记
# filter_backends = [DjangoFilterBackend]
# filterset_fields=['name','price']
-方式三:自定义--完全自己控制
# http://127.0.0.1:8000/books/?price=19&name=书
# filter_backends = [MyFilter] # 我自己知道按哪些字段过滤
# 需要写过滤类(下面)
视图
from .models import Book
from .serializer import BookSerializer
from rest_framework.viewsets import ViewSetMixin
from rest_framework.generics import ListAPIView
from rest_framework.filters import SearchFilter
from django_filters.rest_framework import DjangoFilterBackend
from .filters import MyFilter
# 方式一:内置的,模糊匹配
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
# filter_backends = [SearchFilter, OrderingFilter]
# search_fields = ['name','price']
# 方式二:第三方,精准匹配
# filter_backends = [DjangoFilterBackend]
# filterset_fields =['name','price']
# 方式三.自定义
filter_backends = [MyFilter]
filter.py
from rest_framework.filters import BaseFilterBackend
from django.db.models import Q
class MyFilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
# 基于queryset 进行过滤,过滤后返回即可
# http://127.0.0.1:8000/books/?name=书 # 名字中有书的就查出来
search_param = request.query_params.get('name')
price = request.query_params.get('price')
if search_param and price:
# queryset = queryset.filter(Q(name__contains=search_param) | Q(price=price)) # qs对象的filter
queryset = queryset.filter(name__contains=search_param,price=price) # qs对象的filter
return queryset
补充:

1.1 继承APIView写过滤和排序
#### 继承APIView 写过滤,写排序
class BookView(ViewSetMixin, APIView):
def list(self, request, *args, **kwargs):
# 按名字过滤
print('asfdasdf')
name = request.query_params.get('name')
book_list = Book.objects.all().filter(name__contains=name)
ser = BookSerializer(instance=book_list, many=True)
return Response(ser.data)
1.2 继承GenericAPIView写过滤类,可以写多个
写多个,他们是从左往右,依次执行
大原则,配置多个过滤类的时候,第一个放尽量多个过滤掉数据
配置多个:执行原理
-先执行第一个过滤类的:filter_queryset返回qs对象
-再执行第二个过滤类的filter_queryset,传入上一个返回的qs,过滤完返回qs对象
2 分页
-
只针对于 查询所有接口:💃
- 分页展现形式:
web : 下一页,下一页
小程序,app:上拉加载更多
- 分页展现形式:
-
必须继承 GenericAPIView 😋
-
使用方式:三种分页方式--drf提供的🐋
- 方式一:基本分页
page.py
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
class CommonPageNumberPagination(PageNumberPagination):
# web 用这个多
# http://api.example.org/accounts/?page=4
# http://api.example.org/accounts/?page=4&page_size=100
# 重写几个类属性
page_size = 3 # 每页显示多少条
page_query_param = 'page' # 指定第几页的key 值 page=4
page_size_query_param = 'size' # 可以指定每页显示多少条 size=300000
max_page_size = 5 # 每页最多显示5条
class CommonLimitOffsetPagination(LimitOffsetPagination):
# http://api.example.org/accounts/?limit=4 # 从开始取4条
# http://api.example.org/accounts/?offset=4&limit=5 从第4条开始,取5条
default_limit = 2 # 默认每页显示2条
limit_query_param = 'limit' # 每页显示多少条的查询条件
offset_query_param = 'offset' # 从第几条开始取数据
max_limit = 5 # limit最多取5条
class CommonCursorPagination(CursorPagination):
# app上用这个多
# 只能上一页和下一页,不能指定跳转到中间的某页---》效率高,大数据量用它、
cursor_query_param = 'cursor' # 查询条件,用不到,需要有
page_size = 2 # 每页显示两条
ordering = 'id' # 按id排序 这个必须是表中字段
视图类:继承GenericAPIView
from .page import CommonPageNumberPagination,CommonLimitOffsetPagination,CommonCursorPagination
class BookView(ViewSetMixin, ListAPIView):
authentication_classes=[]
queryset = Book.objects.all()
serializer_class = BookSerializer
# pagination_class =CommonCursorPagination # 分页方式只有一种,配置一个类即可
# pagination_class = CommonLimitOffsetPagination
pagination_class = CommonCursorPagination


继承APIView实现
class BookView(ViewSetMixin, APIView):
authentication_classes=[]
def list(self,request,*args,**kwargs):
book_list=Book.objects.all()
pagination =CommonPageNumberPagination()
page=pagination.paginate_queryset(book_list,request)
ser=BookSerializer(instance=page,many=True)
return Response(ser.data)

3 异常处理
三大认证 视图类的方法中执行出错,都会被全局异常捕获
-认证类,认证不通过,抛异常,前端看到没有问题,只是返回了提示信息---》处理了drf的异常
drf全局异常处理,他会把drf的异常处理掉,统一返回格式,但是django原生的和python的都不会处理
# 我们要做的,无论什么异常,都返回固定格式
1 写一个函数
def common_exception(exc, context):
# 执行一下原来的exception_handler---》它能处理drf的异常,我就不用处理了
res = exception_handler(exc, context)
if not res: # 有值,说明是drf异常,它处理完了,没有值,是其他异常,我们自己处理
return Response({'code': 999, 'msg': '非drf错误,错误信息是:%s' % str(exc)})
else:
return Response({'code': 888, 'msg': 'drf错误,错误信息是:' + res.data.get('detail')})
2 配置文件配置
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'app01.exceptions.common_exception', # 以后只要出了异常,都会走这个函数.
}
总结:
- 写一个函数
- 执行一下原来的exception_handler---》它能处理drf的异常,我就不用处理了
- 判断如果有值,说明是drf异常,它处理完了,没有值,是其他异常,我们自己处理
- 配置文件配置'EXCEPTION_HANDLER': 'app01.exceptions.common_exception',以后只要出了异常,都会走这个函数

补充:
1. DateField、DateTimeField
-auto_now_add=True # 创建数据时自动添加当前时间
-auto_now=True # 每次操作数据时更新为当前时间
2. session认证的原理


浙公网安备 33010602011771号