首页 > 其他分享 >【九】DRF之过滤排序异常

【九】DRF之过滤排序异常

时间:2023-07-31 12:23:09浏览次数:38  
标签:rest page framework 过滤 DRF import 排序 class size

【一】过滤(Filtering)

  • 对于列表数据可能需要根据字段进行过滤
    • 我们可以通过添加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

【二】排序(Ordering)

  • 对于列表数据
    • 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 DjangoFilterBackend
class Student3ListView(ListAPIView):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer
    filter_fields = ('age', 'sex')
    # 因为局部配置会覆盖全局配置,所以需要重新把过滤组件核心类再次声明,
    # 否则过滤功能会失效
    filter_backends = [OrderingFilter,DjangoFilterBackend]
    ordering_fields = ('id', 'age')

【三】分页(Pagination)

  • REST framework提供了分页的支持。
  • 我们可以在配置文件中设置全局的分页方式,如:
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 100  # 每页数目
}
  • 也可通过自定义Pagination类,来为视图添加不同分页行为。
  • 在视图中通过pagination_clas属性来指明。
class LargeResultsSetPagination(PageNumberPagination):
    page_size = 1000
    page_size_query_param = 'page_size'
    max_page_size = 10000
class BookDetailView(RetrieveAPIView):
    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer
    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 前端最多能设置的每页数量

基本使用(APIView)

# APIView
from rest_framework.pagination import PageNumberPagination
# 一 基本使用:url=url=http://127.0.0.1:8000/pager/?page=2&size=3,size无效
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)
        # 对分页进行序列化
        ser=BookSerializer1(instance=page_list,many=True)
        return Response(ser.data)

自定制(APIView)

# 二 自定制 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

#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

# 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

#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:按什么排序,需要指定

APIView

#APIView
from rest_framework.pagination import CursorPagination
# 看源码,是通过sql查询,大于id和小于id
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

# ListAPIView
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

【2】应用

from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
class MyPageNumberPagination(PageNumberPagination):
    page_size = 2
    page_query_param = 'page'
    # 定制传参
    page_size_query_param = 'size'
    # 最大一页的数据
    max_page_size = 5

class MyLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 2
    # 最大一页的数据
    max_limit = 5
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

四 异常处理(Exceptions)

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

【1】使用方式

from rest_framework.views import exception_handler

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

【2】案例

  • 补充上处理关于数据库的异常
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'
}

【3】REST framework定义的异常

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

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

标签:rest,page,framework,过滤,DRF,import,排序,class,size
From: https://www.cnblogs.com/dream-ze/p/17593123.html

相关文章

  • 【十一】DRF之JWT认证
    【一】JWT认证在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证。我们不再使用Session认证机制,而使用JsonWebToken(本质就是token)认证机制。Jsonwebtoken(JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC7519)该to......
  • 【十二】DRF之RBAC控制
    【一】什么是RBAC【1】概念RBAC是基于角色的访问控制(Role-BasedAccessControl)在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计......
  • 归并排序
    求逆序对我用的是归并排序直接上我在洛谷里做的那道逆序对的题目的归并排序主要代码吧1voidmsort(intl,intr){2if(l>=r)return;3intmid=(l+r)>>1;4msort(l,mid);5msort(mid+1,r);6inti=l,j=mid+1,k=l;7......
  • C#冒泡排序算法
    冒泡排序实现原理冒泡排序是一种简单的排序算法,其原理如下:从待排序的数组的第一个元素开始,依次比较相邻的两个元素。如果前面的元素大于后面的元素(升序排序),则交换这两个元素的位置,使较大的元素“冒泡”到右侧。继续比较下一对相邻元素,重复步骤2,直到遍历到数组的倒数第二......
  • numpy-选择和过滤
    numpy-选择和过滤目录numpy-选择和过滤查找np,where()np.extract()比较数组和单个数字数组和数组过滤单条件过滤多条件过滤查找np,where()1、不带条件返回tuple,第一个值是索引,第二个是空值输入必须是数组,不能是list输入一般是一维,行向量或者列向量都可以2、带条件np.wh......
  • 关于排序的一些小问题
    快速排序模板voidquick_sort(inta[],intl,intr){if(l>=r)return;inti=l-1,j=r+1;x=q[l+r>>1];while(i<j){doi++;while(a[i]<x);doj--;while(a[j]>x);if(i<j)swap(a[i],a[j]);quick_sort(a,l,j),quick_sort(a,j+1,......
  • Java中过滤出ListA和ListB中字段相同的集合
    Java中过滤出ListA和ListB中age字段相同的User集合在Java中,List是一种常见的集合类型,它可以用来存储一组有序的数据。而对于List中存储的对象类型,我们可以使用泛型来进行限定。假设我们现在有两个List集合,分别为ListA和ListB,它们都存储了一些User对象。现在我们需要从这两个集合......
  • 【Python】使用 pyecharts 模块绘制动态时间线柱状图 ① ( 列表排序 | 使用 sorted 函
    文章目录一、列表排序1、使用sorted函数对容器进行排序2、使用list.sort函数对列表进行排序3、使用list.sort函数对列表进行排序-设置排序函数4、使用list.sort函数对列表进行排序-设置lambda匿名排序函数pyecharts画廊网站:https://gallery.pyecharts.org/#/......
  • 无涯教程-jQuery - Sortable排序函数
    能够排序功能可与JqueryUI中的交互配合使用。此功能可在任何DOM元素上启用可排序功能。单击并将其拖动到列表中的新位置,其他项将调整以适合。默认情况下,可排序项目共享可拖动属性。Sortable-语法$(function(){$("#sortable").sortable();$("#sortable").disabl......
  • 冒泡排序
    #include<stdio.h>voidbubble_sort(intarr[],intsz){ inti=0; for(i=0;i<sz-1;i++) { intj=0; for(j=0;j<sz-1-i;j++) { if(arr[j]>arr[j+1]) { inttmp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=tmp; } } }}intmain()......