DRF过滤排序分页异常处理的过程记录

目录
    • pagenumberpagination
    • limitoffsetpagination
    • cursorpagination
    • 继承apiview使用方法
  • 五、封装response对象

      一、过滤

      对于列表数据要通过字段来进行过滤,就需要添加 django-filter 模块

      使用方法:

      # 1、注册,在app中注册 settings.py
      installed_apps = [
          'django_filters',
      ]
      
      # 2、settings.py 配置
      rest_framework = {
          'default_filter_backends': (
              'django_filters.rest_framework.djangofilterbackend',
          )
      }
      
      # 3、在视图中添加filter_fields属性,指定过滤的字段
      class booksview(modelviewset):
          queryset = books.objects.all()
          serializer_class = booksserializer
      
          filter_fields = ('title',) # 配置可以按照哪个字段来过滤
          
      # http://127.0.0.1:8000/books/?title=红楼梦
      
      

      二、排序

      排序可以使用 rest framework 提供的 orderingfilter 来快速指明数据按指定字段进行排序

      使用方法:

      # 1、首先视图中设置filter_backends=[orderingfilter]
      # 2、然后再视图中添加 ordering_fields 属性,指定排序字段
      
      from rest_framework.filters import orderingfilter
      class booksview(modelviewset):
          queryset = books.objects.all()
          serializer_class = booksserializer
      
          filter_backends = [orderingfilter] # 第一步
          ordering_fields = ['price','id'] # 第二步
          
      # http://127.0.0.1:8000/books/?ordering=id 通过ordering查看有无指明排序的字段,并通过字段来排序
      # -id 表示针对id字段进行倒序排序
      # id  表示针对id字段进行升序排序
      
      

      三、分页

      首先 rest framework 提供了三种分页方式,并且

      • pagenumberpagination
      • limitoffsetpagination
      • cursorpagination

      使用方式一:可以直接继承使用,但是配置参数需要在settings.py里面配置

      使用方式二:通过子类继承父类分页器使用,直接在子类中修改父类的参数(推荐)

      pagenumberpagination

      子类中的属性:

      • page_size:每页数目
      • page_query_param:前端发送的页数关键字,默认“page”
      • page_size_query_param:前端发送每页数目关键字名,默认none
      • max_page_size:前端最多能设置的每页数量

      如何使用:

      from rest_framework.generics import listapiview
      from rest_framework.pagination import pagenumberpagination
      from app01.models import books
      from app01.ser import booksserializer
      
      # 第一步:
      class bookpagenumberpagination(pagenumberpagination):
          page_size = 3         # 每页条数
          page_query_param = 'page'   # 查询第几页的key
          page_size_query_param = 'size'  # 每一页显示的条数
          max_page_size = 5   # 每页最大条数
      
      
      class bookview(listapiview):
          queryset = books.objects.all()
          serializer_class = booksserializer
          
          # 第二步:分页配置
          pagination_class = bookpagenumberpagination
          
          
      # url:http://127.0.0.1:8000/books/?page=1&size=5 查询第1页,一共显示五条数据
      
      

      limitoffsetpagination

      子类中的属性:

      • default_limit:默认限制,默认值与page_size设置一致
      • limit_query_param:limit参数名,默认’limit’
      • offset_query_param:offset参数名,默认’offset’
      • max_limit:最大limit限制,默认none

      如何使用:

      from rest_framework.generics import listapiview
      from rest_framework.pagination import limitoffsetpagination
      from app01.models import books
      from app01.ser import booksserializer
      
      # 第一步:
      class booklimitoffsetpagination(limitoffsetpagination):
          default_limit = 3           # 每页条数
          limit_query_param = 'limit'     # 往后拿几条
          offset_query_param = 'offset'   # 从第几条往后拿几条的标杆
          max_limit = 5       # 每页最大拿几条
      
      
      class bookview(listapiview):
          queryset = books.objects.all()
          serializer_class = booksserializer
          
          # 第二步:分页配置
          pagination_class = booklimitoffsetpagination
          
          
      # url:http://127.0.0.1:8000/books/?limit=3&offset=4  从第三条开始往后拿4条数据
      
      

      cursorpagination

      子类中的属性:

      • cursor_query_param:默认查询字段,不需要修改
      • page_size:每页数目
      • ordering:按什么排序,需要指定

      如何使用:

      cursorpagination的查询速度快,但是却不能定位到第几页这样查,要么往前查,要么往后查。

      from rest_framework.generics import listapiview
      from rest_framework.pagination import cursorpagination
      from app01.models import books
      from app01.ser import booksserializer
      
      # 第一步:
      class bookcursorpagination(cursorpagination):
          cursor_query_param = 'cursor'   # 每页查询的key
          page_size = 3       # 每页显示条数
          ordering = 'id'    # 排序字段
      
      
      class bookview(listapiview):
          queryset = books.objects.all()
          serializer_class = booksserializer
          
          # 第二步:分页配置
          pagination_class = bookcursorpagination
          
          
      # url:http://127.0.0.1:8000/books/?cursor=cd0z
      
      

      继承apiview使用方法

      像方式一,方式二这样使用的话,就要视图类是继承 listapiview 然后直接配置就可以了

      但是如果视图类继承的是 genericapiview 或者 apiview 的话,就需要用另一种方式了:

      使用方法:

      # 1、定义一个分页器
      class bookpagenumberpagination(pagenumberpagination):
          page_size = 3         # 每页条数
          page_query_param = 'page'   # 查询第几页的key
          page_size_query_param = 'size'  # 每一页显示的条数
          max_page_size = 5   # 每页最大条数
      
      
      class bookview(apiview):
      
          def get(self, request, *args, **kwargs):
              book_list = books.objects.all()
      
              # 2、实例化得到一个分页器对象
              page_obj = bookpagenumberpagination()
              
              # 3、调用paginate_queryset返回每一页的数据
              book_list = page_obj.paginate_queryset(book_list, request, view=self)
      
              # 4、获取上一页下一页链接
              next_url = page_obj.get_next_link()
              previous_url = page_obj.get_previous_link()
      
              # 5、序列化
              book_ser = booksserializer(book_list, many=true)
              
              # 6、加入响应信息中
              data = {'next_url': next_url, 'previous_url': previous_url, 'data': book_ser.data}
              return response(data=data)
      
      

      四、异常处理

      异常处理主要是用来统一接口返回

      源码分析

      异常处理在apiview的api_settings已经配置好了

      ‘exception_handler’: ‘rest_framework.views.exception_handler’,

      def exception_handler(exc, context):
          # 先判断是不是404
          if isinstance(exc, http404): # exc是异常信息的异常对象
              exc = exceptions.notfound()
          # 然后判断是不是权限的问题
          elif isinstance(exc, permissiondenied):
              exc = exceptions.permissiondenied()  # 比如权限问题会返回一个字典
              
       # 在判断你抛出的是不是api的异常——>认证权限这些都是继承了api的异常
          if isinstance(exc, exceptions.apiexception):
              headers = {}
              if getattr(exc, 'auth_header', none):
                  headers['www-authenticate'] = exc.auth_header
              if getattr(exc, 'wait', none):
                  headers['retry-after'] = '%d' % exc.wait
      
              if isinstance(exc.detail, (list, dict)):
                  data = exc.detail
              else:
                  data = {'detail': exc.detail}
      
              set_rollback()
              return response(data, status=exc.status_code, headers=headers)
          # 只要是上面这些异常都做了处理
         
      
          return none  # 意味有些异常它没有处理,就会交给django自己处理
      
      

      如何处理

      因为dir有些异常它不做处理,django处理的又不符合我们的标准,所以就要写一个统一的异常类来替换掉它,把所有情况都处理,只要前端出异常看到的都是固定的东西。

      如何写:

      重写一个类,和它基本上差不多,配置的时候在 settings.py 里面全局配置

      #  app01_auth.py
      from rest_framework.views import exception_handler
      from rest_framework.response import response
      
      def app01_exception_handler(exc, context):
          response = exception_handler(exc, context)  # 原来的drf处理的我们也需要
          # 两种情况,一个是none,drf没有处理,django处理了,但是处理的不符合需求
          # response对象,drf处理了我们需要的
      
      
          if not response:
              # 如果没处理,那么我们自己处理
              return response(data={'status': 400, 'error': str(exc)}, status=400)
          else:
              # drf 处理了,那么取出它处理的信息,重新处理一下
              return response(data={'status': 400, 'error': response.data.get('detail')}, status=400)
      
      

      然后再全局配置一下:settings.py

      rest_framework = {
          'exception_handler': 'app01.app_auth.app01_exception_handler',
      }
      

      五、封装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)
              
              
      # 使用
      return apiresponse(data={"name":'xiaoyang'},token='dsafsdfa',aa='dsafdsfdee')
      return apiresponse(data={"name":'xiaoyang'})
      return apiresponse(code='101',msg='错误',data={"name":'xiaoyang'},token='dsafsdfa',aa='dsafdsfdee',header={})
      

      总结

      到此这篇关于drf过滤排序分页异常处理的文章就介绍到这了,更多相关drf过滤排序分页内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

      (0)
      上一篇 2022年3月21日
      下一篇 2022年3月21日

      相关推荐