drf08 过滤、排序、分页、异常

一、过滤Filtering

对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持。

1.安装

# 1.安装
pip install django-filter

# 2.在settings的app中注册
INSTALLED_APPS = [
    'django_filters',  # 需要注册应用,
]

2.全局配置

from rest_framework import settings

REST_FRAMEWORK = {
    # filters - Generic view behavior
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
}

3.局部配置

from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from app05_api.models import Book
from app05_api.ser import BookModelSerializer
# 过滤
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter


class BookModelViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    # 过滤 - 配置可以按照哪个字段来过滤
    # http://127.0.0.1:8000/app_auth/books/?title=赵张三李四历险
    # filter_backends = [DjangoFilterBackend]
    filter_fields = ('id','title', 'price')

4.访问

 http://127.0.0.1:8000/app_auth/books/?title=赵张三李四历险

二、排序 OrderingFilter

对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。

使用方法:

在类视图中设置filter_backends,使用rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。

前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。

1. 全局配置

from rest_framework import settings

REST_FRAMEWORK = {
    # 设置排序过滤
   'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.OrderingFilter',],
}

2. 局部配置

from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from app05_api.models import Book
from app05_api.ser import BookModelSerializer
# 过滤
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter


class BookModelViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    # 排序 http://127.0.0.1:8000/app_auth/books/?ordering=-id
    filter_backends = [OrderingFilter]
    ordering_fields = ('id', 'price')
    # 必须是ordering=某个值
    # -id 表示针对id字段进行倒序排序
    # id  表示针对id字段进行升序排序

3. 访问

http://127.0.0.1:8000/app_auth/books/?ordering=-id

4.总结 - 过滤+排序

如果需要在过滤以后再次进行排序,则需要两者结合!

from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from app05_api.models import Book
from app05_api.ser import BookModelSerializer
# 过滤
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter


class BookModelViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    # 过滤 - 配置可以按照哪个字段来过滤
    filter_backends = [DjangoFilterBackend,OrderingFilter]
    filter_fields = ('id','title', 'price')
    ordering_fields = ('id', 'price')


# 访问

http://127.0.0.1:8000/app_auth/books/?price=3453.44&ordering=-id

三、分页

1.分页类型

1.1 PageNumberPagination -常用

前端访问网址形式:

# http://127.0.0.1:8000/api/books/?page=1&size=2
# 解释: page 当前页   size 展示条数
  • page_size 每页数目
  • page_query_param 前端发送的页数关键字名,默认为"page"
  • page_size_query_param 前端发送的每页数目关键字名,默认为None
  • max_page_size 前端最多能设置的每页数量
# http://127.0.0.1:8000/api/books/?page=1&size=2
# 解释: page 当前页   size 展示条数


class MyPageNumberPagination(PageNumberPagination):

    page_size=3  #每页条数
    page_query_param='page' #查询第几页的key - 参数可自己设置
    page_size_query_param='size' # 每一页显示的条数 - 参数可自己设置
    max_page_size=5    # 每页最大显示条数 - 多了不显示

1.2 LimitOffsetPagination

前端访问网址形式:

# http://127.0.0.1:8000/app_auth/books/?limit=2&offset=2
# 解释: offset 偏移量  limit 展示条数  - 用法同sql的分页类似

可以在子类中定义的属性:

  • default_limit 默认限制,每页数据量大小,默认值与PAGE_SIZE设置一致
  • limit_query_param limit参数名,默认'limit' , 可以通过这个参数来改名字
  • offset_query_param offset参数名,默认'offset' ,可以通过这个参数来改名字
  • max_limit 最大limit限制,默认None, 无限制
# http://127.0.0.1:8000/app_auth/books/?limit=2&offset=2
# 解释: offset 偏移量  limit 展示条数  - 用法同sql的分页类似

class MyLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 3   # 每页条数
    limit_query_param = 'limit' # 往后拿几条
    offset_query_param = 'offset' # 标杆
    max_limit = 5   # 每页最大几条

1.3 CursorPagination -速度最快

前端访问网址形式:

# http://127.0.0.1:8000/app_auth/books/?ordering=id
# 解释: 速度最快 只需要指定字段排序

可以在子类中定义的属性:

  • cursor_query_param 默认'cursor’,可以通过这个参数来改名字
  • page_size 每页显示条数
  • ordering 排序字段
# http://127.0.0.1:8000/app_auth/books/?ordering=id
# 解释: 速度最快 只需要指定字段排序

class MyCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'  # 每一页查询的key
    page_size = 2   #每页显示的条数
    ordering = '-id'  #排序字段

2.全局配置

from rest_framework import settings

REST_FRAMEWORK = {
    # Pagination
    # 设置每页大小
    # 'DEFAULT_PAGINATION_CLASS':
                                # 'rest_framework.pagination.PageNumberPagination',
                                # 'rest_framework.pagination.LimitOffsetPagination',
                                # 'rest_framework.pagination.CursorPagination',

    'PAGE_SIZE': 3,
}

3.局部配置

from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from app05_api.models import Book
from app05_api.ser import BookModelSerializer
# 过滤
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter


class BookModelViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer
    # 分页
    pagination_class =PageNumberPagination
  # pagination_class =LimitOffsetPagination
  # pagination_class =CursorPagination			

4.自定义分页 - 可选

from rest_framework.pagination import PageNumberPagination

class MyPageNumberPagination(PageNumberPagination):
    page_size = 3  # 每页条数
    page_query_param = 'page'  # 查询第几页的key - 参数可自己设置
    page_size_query_param = 'size'  # 每一页显示的条数 - 参数可自己设置
    max_page_size = 5  # 每页最大显示条数 - 多了不显示


from rest_framework.pagination import LimitOffsetPagination

class MyLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 3  # 每页条数
    limit_query_param = 'limit'  # 往后拿几条
    offset_query_param = 'offset'  # 标杆
    max_limit = 5  # 每页最大几条


from rest_framework.pagination import CursorPagination

class MyCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'  # 每一页查询的key
    page_size = 2  # 每页显示的条数
    ordering = '-id'  # 排序字段

使用

# views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from app05_api.models import Book
from app05_api.ser import BookModelSerializer
from app06_auth.utils.app_pagination import MyPageNumberPagination,MyLimitOffsetPagination,MyCursorPagination

class BookView(APIView):
    # throttle_classes = [MyThrottle,]
    def get(self,request,*args,**kwargs):
        book_list=Book.objects.all()
        # 实例化得到一个分页器对象
        page_cursor=MyPageNumberPagination()
        # page_cursor=MyLimitOffsetPagination()
        # page_cursor = MyCursorPagination()
        
        book_list=page_cursor.paginate_queryset(book_list,request,view=self)
        next_url =page_cursor.get_next_link()
        pr_url=page_cursor.get_previous_link()
        # print(next_url)
        # print(pr_url)
        book_ser=BookModelSerializer(book_list,many=True)
        data = {'next_url':next_url,
                'pr_url':pr_url,
                'data':book_ser.data}
        return Response(data=data)

    
    
# urls.py
from django.urls import path, re_path
from rest_framework import routers
from app06_auth import views
urlpatterns = [
    path('book/', views.BookView.as_view()),
]

5.总结:

-使用:
        继承了APIView的视图类中使用
        	 page=Mypage()
            # 在数据库中获取分页的数据
            page_list=page.paginate_queryset(queryset对象,request,view=self)
            # 对分页进行序列化
            ser=BookSerializer1(instance=page_list,many=True)
            # return Response(ser.data)
        继承了视图子类的视图中使用
        	 pagination_class = PageNumberPagination(配置成自己重写的,可以修改字段)

四、异常处理

REST framework提供了异常处理,我们可以自定义异常处理函数。

可以创建一个utils文件夹,里面放一个exceptions.py文件,名字随便写,然后写下面的内容

1. 自定义异常处理

# 自定义异常处理的方法
from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status
def my_exception_handler(exc, context):
    response=exception_handler(exc, context)
    # exc 异常类型 context
    # 两种情况,一个是None,drf没有处理
    #response对象,django处理了,但是处理的不符合咱们的要求
    # print(type(exc))

    if not response:
        if isinstance(exc, ZeroDivisionError):
            return Response(data={'status': 777, 'msg': "除以0的错误" + str(exc)}, status=status.HTTP_400_BAD_REQUEST)
        return Response(data={'status':999,'msg':str(exc)},status=status.HTTP_400_BAD_REQUEST)
    else:
        # return response
        return Response(data={'status':888,'msg':response.data.get('detail')},status=status.HTTP_400_BAD_REQUEST)

使用

# views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from app05_api.models import Book
from app05_api.ser import BookModelSerializer
from app06_auth.utils.app_pagination import MyPageNumberPagination,MyLimitOffsetPagination,MyCursorPagination

class BookView(APIView):
    # throttle_classes = [MyThrottle,]
    def get(self,request,*args,**kwargs):
        # 设置一个错误
        # 1/0
        
        book_list=Book.objects.all()
        # 实例化得到一个分页器对象
        page_cursor=MyPageNumberPagination()
        # page_cursor=MyLimitOffsetPagination()
        # page_cursor = MyCursorPagination()
        
        book_list=page_cursor.paginate_queryset(book_list,request,view=self)
        next_url =page_cursor.get_next_link()
        pr_url=page_cursor.get_previous_link()
        # print(next_url)
        # print(pr_url)
        book_ser=BookModelSerializer(book_list,many=True)
        data = {'next_url':next_url,
                'pr_url':pr_url,
                'data':book_ser.data}
        return Response(data=data)

    
    
# urls.py
from django.urls import path, re_path
from rest_framework import routers
from app06_auth import views
urlpatterns = [
    path('book/', views.BookView.as_view()),
]

2. REST framework定义的异常

  • APIException 所有异常的父类
  • ParseError 解析错误
  • AuthenticationFailed 认证失败
  • NotAuthenticated 尚未认证
  • PermissionDenied 权限决绝
  • NotFound 未找到
  • MethodNotAllowed 请求方式不支持
  • NotAcceptable 要获取的数据格式不支持
  • Throttled 超过限流次数
  • ValidationError 校验失败

也就是说,上面列出来的异常不需要我们自行处理了,很多的没有在上面列出来的异常,就需要我们在自定义异常中自己处理了。

五、响应

1. 自定义封装Response

from rest_framework.response import Response
class APIResponse(Response):
    def __init__(self,code=100,msg='成功',data=None,status=None,headers=None,**kwargs):
        dic = {'code': code, 'msg': msg}
        if  data:
            dic = {'code': code, 'msg': msg,'data':data}
        dic.update(kwargs)
        super().__init__(data=dic, status=status,headers=headers)

2. 使用

from rest_framework.views import APIView
from app05_api.models import Book
from app05_api.ser import BookModelSerializer
from app06_auth.utils.app_response import APIResponse

class BookView(APIView):
    # throttle_classes = [MyThrottle,]
    def get(self,request,*args,**kwargs):
        # 设置一个错误
        # 1/0
        book_list=Book.objects.all()
        # 实例化得到一个分页器对象
        page_cursor=MyPageNumberPagination()
        # page_cursor=MyLimitOffsetPagination()
        # page_cursor = MyCursorPagination()
        book_list=page_cursor.paginate_queryset(book_list,request,view=self)
        next_url =page_cursor.get_next_link()
        pr_url=page_cursor.get_previous_link()
        # print(next_url)
        # print(pr_url)
        book_ser=BookModelSerializer(book_list,many=True)
        data = {'next_url':next_url,
                'pr_url':pr_url,
                'data':book_ser.data}

        # return Response(data=data)
        return APIResponse(data={"name": 'zs'}, token='123', aa='123456')

3.访问

http://127.0.0.1:8000/app_auth/book/
posted @ 2023-05-31 10:02  派森的猫  阅读(9)  评论(0编辑  收藏  举报