七:drf-过滤排序异常处理分页

接上一篇:六:drf-认证权限频率

一:过滤Filtering

使用总结:
	1. 安装-pip install django-filter
	2. 注册-在APP中注册
	3. 全局配,或者局部配
	4. 视图类

对于列表数据可能需要根据字段进行过滤,我们可以通过添加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 = StudentSerializer
    # 配置可以按照哪个字段来过滤
    filter_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 = StudentModelSerializer
    filter_backends = [OrderingFilter]
    ordering_fields = ('id', 'age')
    # 127.0.0.1:8000/books/?ordering=-age
	# -id 表示针对id字段进行倒序排序
	# id  表示针对id字段进行升序排序

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

from rest_framework.generics import ListAPIView
from students.models import Student
from .serializers import StudentModelSerializer
from django_filters.rest_framework import OrderingFilter, DjangoFilterBackend
class Student3ListView(ListAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
    filter_fields = ('age', 'sex')
    # 因为局部配置会覆盖全局配置,所以需要重新把过滤组件核心类再次声明,
    # 否则过滤功能会失效
    filter_backends = [OrderingFilter,DjangoFilterBackend]
    ordering_fields = ('id', 'age')

三:异常

REST framework提供了异常处理,我们可以自定义异常处理函数。
统一接口返回

使用方式

from rest_framework.views import exception_handler

def my_exception_handler(exc, context):
    # 先调用REST framework默认的异常处理方法获得标准错误响应对象
    response = exception_handler(exc, context)

    # 在此处补充自定义的异常处理
    if response is None:
        response.data['status_code'] = response.status_code

    return 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'
}

案例:处理关于数据库的异常

from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework import status
from django.db import DatabaseError

def 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'
}

四:分页

REST framework提供了分页的支持。

我们可以在配置文件中设置全局的分页方式,如:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 100  # 每页数目
}

也可通过自定义Pagination类,来为局部视图添加不同分页行为。在视图中通过pagination_class属性来指明。

# 自定义分页类
class LargeResultsSetPagination(PageNumberPagination):
    page_size = 10
    # 前端发送的每页数目关键字名
    page_size_query_param = 'page_size'
    # 设置查询的每页最多的数量
    max_page_size = 20
    
class BooksView(ListAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookModelSerializer
    # 配置分页
    pagination_class = LargeResultsSetPagination

注意:如果在视图内关闭分页功能,只需在视图内设置(局部禁用

	pagination_class = None

1 三种内置分页器

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: 前端最多能设置的每页数量
from rest_framework.pagination import PageNumberPagination
# 一 基本使用:url=url=http://127.0.0.1:8000/pager/?page=2&size=3,size无效
"""# 使用APIView(或者GenericAPIView)进行分页"""
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)
        """ 产生下一页上一页的url"""
        next_url = page.get_next_link()
        pre_url = page.get_previous_link()
         # 对分页进行序列化
        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
2)LimitOffsetPagination

前端访问网址形式:

GET   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
"""
# 使用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
3)CursorPagination

这种分页器,只能上一页下一页,但是速度比前两种快。

前端访问网址形式:

GET   http://127.0.0.1/four/students/?cursor=cD0xNQ%3D%3D

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

  • cursor_query_param:默认查询字段,不需要修改
  • page_size:每页数目
  • ordering:按什么排序,需要指定
"""看源码,是通过sql查询,大于id和小于id"""
"""
使用APIView进行分页
"""
class  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)

"""
使用ListAPIView进行分页
"""    
from rest_framework.pagination import CursorPagination
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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值