DRF ---- 过滤组件 分页组件 过滤组件插件使用

目录

  • DRF过滤组件

    • 1 源码分析:
    • 2 全局配置 过滤 类们
    • 3 局部配置 过滤 类们
    • 4 系统提供 过滤 类们
      • OrderingFilter(排序过滤)
      • SearchFilter(查询过滤)
      • 联合使用
  • DRF分页组件
    • 1 全局配置
    • 2 局部配置
    • 3 PageNumberPagination基础分页
    • 4 LimitOffsetPagination偏移分页
    • 5 CursorPagination游标分页 加密分页(了解)
    • 6.自定义过滤器
  • 7 django-filter 过滤插件(重点)
    • 安装
    • 自定义过滤规则类:filters.py
    • 的视图类:views.py

DRF过滤组件

1 源码分析:

入口: 群查 ListModelMixin 内的 list 但是方法都由 GenericAPIView 提供

    def list(self, request, *args, **kwargs):

        # 过滤queryset 对象 得到 queryset 对象 方法都在 GenericApiView 里面
        queryset = self.filter_queryset(self.get_queryset())
        # 分页组件
        page = self.paginate_queryset(queryset)

        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

GenericAPIView 找到 filter_queryset

def filter_queryset(self, queryset):
    # 从配置文件中拿到 filter_backends 循环 然后调用 犯法 filter_queryset
    for backend in list(self.filter_backends):
        # filter_backends 就是过滤类们 且 产生的对象 都有 filter_queryset 方法
        queryset = backend().filter_queryset(self.request, queryset, self)
    return queryset

2 全局配置 过滤 类们

filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
'DEFAULT_FILTER_BACKENDS': [], # 全局配置默认为 [] 

3 局部配置 过滤 类们

class Test(generics.GenericAPIView, mixins.ListModelMixin):
    ....
    filter_backends = []

    def get(self, request, *args, **kwargs):
        self.list(request,args, **kwargs)

4 系统提供 过滤 类们

restframework 中 找到 filter.py 里面 默认提供了 两个 过滤类 都是继承的BaseFilterBackend且 都有 filter_queryset 方法 他啥都不用继承

class BaseFilterBackend:
    def filter_queryset(self, request, queryset, view):
        # 直接抛异常
        raise NotImplementedError(".filter_queryset() must be overridden.")

OrderingFilter(排序过滤)

view视图

from rest_framework.generics import ListAPIView

# 第一步:drf的OrderingFilter - 排序过滤
from rest_framework.filters import OrderingFilter

class CarListAPIView(ListAPIView):
    queryset = models.Car.objects.all()
    serializer_class = serializers.CarModelSerializer

    # 第二步:局部配置 过滤类 们(全局配置用DEFAULT_FILTER_BACKENDS)
    filter_backends = [OrderingFilter]

    # 第三步:OrderingFilter过滤类依赖的过滤条件 => 接口:/cars/?ordering=...
    ordering_fields = ['pk', 'price']
    # eg:/cars/?ordering=-price,pk,先按price降序,如果出现price相同,再按pk升序

    # 规则:
    #?ordering=price 按价格升序
    #?ordering=-price 按价格降序
    #?ordering=id 按主键升序
    #?ordering=-price,id 按价格降序,价格相同时按主键升序

ordering_fields 里面填写字段 (真实存在的)

接口: 127.0.0.1:8000?ordering=price,name
查询 按照 price 排序后 在按 name 排序的结果
支持升序和降序 加-号即可

SearchFilter(查询过滤)

view视图

from rest_framework.generics import ListAPIView

# 第一步:drf的SearchFilter - 搜索过滤
from rest_framework.filters import SearchFilter

class CarListAPIView(ListAPIView):
    queryset = models.Car.objects.all()
    serializer_class = serializers.CarModelSerializer

    # 第二步:局部配置 过滤类 们(全局配置用 DEFAULT_FILTER_BACKENDS )
    filter_backends = [SearchFilter]

    # 第三步:SearchFilter 过滤类依赖的过滤条件 重点!
    # 接口:/cars/?search=...
    search_fields = ['name', 'price']
    # eg:/cars/?search=1,name和price中包含1的数据都会被查询出

search_fields 里面填写字段 (真实存在的)

接口: 127.0.0.1:8000?search=1
查询 name 和 price 带有 1 的数据

联合使用

127.0.0.1:8000?search=1$ordering=price,name

DRF分页组件

入口: restfarmework 中的 pagination.py 提供了 3 个 分页 类 CursorPagination(游标分页 加密分页) LimitOffsetPagination(偏移分页) PageNumberPagination(基础分页)

且 每一个类都有 方法 paginate_queryset 方法

ef list(self, request, *args, **kwargs):

        # 过滤queryset 对象 得到 queryset 对象 方法都在 GenericApiView 里面
        queryset = self.filter_queryset(self.get_queryset())
        # 分页组件
        page = self.paginate_queryset(queryset)
        # 判断是否有 分页 没有就正常执行 有的话就 执行 get_paginated_response
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

方法也是有 GenericApiView 提供

pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
 def paginate_queryset(self, queryset):
        if self.paginator is None:
            return None
        # 调用配置的
        return self.paginator.paginate_queryset(queryset, self.request, view=self)

1 全局配置

'DEFAULT_PAGINATION_CLASS': None, 默认为None

2 局部配置

from rest_framework.pagination import PageNumberPagination
class Test(generics.GenericAPIView, mixins.ListModelMixin):
    queryset = models.Banner.objects.all()
    serializer_class = serializers.BannerModelSerializer
    pagination_class = [PageNumberPagination]

3 PageNumberPagination基础分页

直接给视图类配置即可 自定义pahenations 修改 参数值 或者直接使用点修改

pahenations.py

from rest_framework.pagination import PageNumberPagination

class MyPageNumberPagination(PageNumberPagination):
    # ?page=页码
    page_query_param = 'page'
    # ?page=页面 下默认一页显示的条数
    page_size = 3
    # ?page=页面&page_size=条数 用户自定义一页显示的条数
    page_size_query_param = 'page_size'
    # 用户自定义一页显示的条数最大限制:数值超过5也只显示5条
    max_page_size = 5

views.py

from rest_framework.generics import ListAPIView

class CarListAPIView(ListAPIView):
    # 如果queryset没有过滤条件,就必须 .all(),不然分页会出问题
    queryset = models.Car.objects.all()
    serializer_class = serializers.CarModelSerializer

    # 分页组件 - 给视图类配置分页类即可 - 分页类需要自定义,继承drf提供的分页类即可
    pagination_class = pagenations.MyPageNumberPagination

4 LimitOffsetPagination偏移分页

使用方式和基本分页器一模一样!

from rest_framework.pagination import LimitOffsetPagination

class MyPageNumberPagination(LimitOffsetPagination):
    # 不设置offset 和 limit 默认显示3条 只设置offset 默认显示后3条
    default_limit = 3
    # ?offset=从头偏移的条数&limit=要显示的条数
    limit_query_param = 'limit'
    offset_query_param = 'offset'
    # 用户自定义一页显示的条数最大限制:数值超过5也只显示5条
    max_limit = None
127.0.0.1:8000?offset=2&limit=3 # 偏移2条 取3条

5 CursorPagination游标分页 加密分页(了解)

from rest_framework.pagination import CursorPagination

class MyPageNumberPagination(CursorPagination):
    cursor_query_param = 'cursor'
    # 显示条数
    page_size = 3
    # 排序
    ordering = '-pk'
    # 用户自定义
    page_size_query_param = None
    # 最大条数
    max_page_size = None

6.自定义过滤器

filters.py

# 自定义过滤器,接口:?limit=显示的条数
class LimitFilter:
    def filter_queryset(self, request, queryset, view):
        # 前台固定用 ?limit=... 传递过滤参数
        limit = request.query_params.get('limit')
        if limit:
            limit = int(limit)
            return queryset[:limit]
        return queryset

views.py

from rest_framework.generics import ListAPIView

class CarListAPIView(ListAPIView):
    # 如果queryset没有过滤条件,就必须 .all(),不然分页会出问题
    queryset = models.Car.objects.all()
    serializer_class = serializers.CarModelSerializer

    # 局部配置 过滤类 们(全局配置用DEFAULT_FILTER_BACKENDS)
    filter_backends = [LimitFilter]

7 django-filter 过滤插件(重点)

分类查询 大白话来讲就是 苏州地区的酒店 可以叫 上海酒店 也可以叫北京大饭店 如果使用 search查询 上海 关于 起名有上海字的酒店的话 苏州的也会被查出来

所以我们需要分类查询 将上海地区分类 然后 在查

安装

>: pip3 install django-filter

自定义过滤规则类:filters.py

# django-filter插件过滤器类
from django_filters.rest_framework.filterset import FilterSet
from . import models

# 自定义过滤字段
from django_filters import filters
class CarFilterSet(FilterSet):
    # 实现区间:field_name关联model表属性,lookup_expr设置过滤规则
    min_price = filters.NumberFilter(field_name='price', lookup_expr='gte')
    max_price = filters.NumberFilter(field_name='price', lookup_expr='lte')
    class Meta:
        model = models.Car
        fields = ['brand', 'min_price', 'max_price']
        # min_price、max_price是自定义字段,需要自己自定义过滤条件
        # 这样就可以使用?brand=xxx来查询了&min_pirce=12

的视图类:views.py

from django_filters.rest_framework import DjangoFilterBackend
from .filters import CourseFilterSet
class FreeCourseListViewSet(ListModelMixin, GenericViewSet):
    queryset = models.Course.objects.filter(is_delete=False, is_show=True).all()
    serializer_class = serializers.CourseModelSerializer

    # 配置过滤组件
    filter_backends = [DjangoFilterBackend]
    # 配置过滤规则的类
    filter_class = CarFilterSet
    # 规则:
    # ?course_category=1 课程分组1所有的课程
    # ?min_price=10 课程价格大于等于10的所有课程
    # ?min_price=10&max_price=100 课程价格大于等于10小于等于100的所有课程

原文地址:https://www.cnblogs.com/lddragon1/p/12189801.html

时间: 2024-09-28 21:38:46

DRF ---- 过滤组件 分页组件 过滤组件插件使用的相关文章

drf框架中分页组件

0922自我总结 drf框架中分页组件 普通分页(最常用) 自定制分页类 pagination.py from rest_framework.pagination import PageNumberPagination # 普通分页 class CarPageNumberPagination(PageNumberPagination): # 默认一页的条数 page_size = 3 # 用户可以自定义选择一页的条数,但最多显示5条 page_size_query_param = 'page_s

bootstrap学习9-路径分页和徽章组件

<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8"> <title>路径分页和徽章组件</title> <link href="css/bootstrap.min.css" rel="stylesheet"> </head> <body style=

组件、控件和插件的区别

组件.插件.控件的区别 控件:是编程中用到的,按钮就算是一个控件,窗口也是等等 组件:是软件的一部分.软件的组成部分. 插件:网页中用到的,flash插件,没有它浏览器不能播放flash. 首先范围最广的应该是组件,英文component,提起组件我们不应该把他和具体的技术,什么dll文件,ocx控件,activex等等联系起来,因为组件仅仅是一个概念,如果非要解释的话,那就是凡是在软件开发中用到了软件的复用,被复用的部分都可以称为组件.构件的英文也是component,所以说构件和组件其实是一

DRF Django REST framework 之 认证组件(五)

引言 很久很久以前,Web站点只是作为浏览服务器资源(数据)和其他资源的工具,甚少有什么用户交互之类的烦人的事情需要处理,所以,Web站点的开发这根本不关心什么人在什么时候访问了什么资源,不需要记录任何数据,有客户端请求,我即返回数据,简单方便,每一个http请求都是新的,响应之后立即断开连接. 而如今,互联网的世界发生了翻天覆地的变化,用户不仅仅需要跟其他用户沟通交流,还需要跟服务器交互,不管是论坛类.商城类.社交类.门户类还是其他各类Web站点,大家都非常重视用户交互,只有跟用户交互了,才能

前端Vue框架 04 路由:逻辑跳转、路由传参 项目组件的数据局部化处理data(){ return{} } 组件的声明周期 组件间通信 各种第三方插件(vuex,axios,element-ui,(jq+bs))

项目初始化 """ 1)根组件:App.vue <template> <div id="app"> <router-view /> </div> </template> 2)路由配置:router/index.js const routes = [ { path: '/', name: 'Home', component: Home } ]; 3)组件:views和components文件夹 i)

(转)Yii的组件机制之一:组件基础类CComponent分析

Yii的组件机制 组件机制,是Yii整个体系的思想精髓,在使用Yii之前,最应该先了解其组件机制,如果不了解这个机制,那么阅读Yii源代码会非常吃力.组件机制给Yii框架赋予了无穷的灵活性和可扩展性,可以毫不夸张地说,Yii框架的基础结构就是组件.大到CApplication对象.控制器.路由管理器(urlManager),小到一些其它插件,均是以组件形式存在的. 什么是Yii组件? Yii中几乎所有可实例化并继承自CComponent的类,均可称为组件. 组件的特点是什么? 继承自CCompo

[js开源组件开发]table表格组件

table表格组件 表格的渲染组件,demo请点击http://lovewebgames.com/jsmodule/table.html,git源码请点击https://github.com/tianxiangbing/table 如上图所示,功能基本包括常用表格中遇到的分页.搜索.删除.AJAX操作.由于是用的HANDLEBARS渲染的,所以样式可能很好的控制,要加新的功能也较容易. 调用例子 html <div class="form"> 名称: <input t

基于ABP模块组件与依赖注入组件的项目插件开发

注意,阅读本文,需要先阅读以下两篇文章,并且对依赖注入有一定的基础. 模块系统:http://www.cnblogs.com/mienreal/p/4537522.html 依赖注入:http://www.cnblogs.com/mienreal/p/4550500.html 正文: 我最近在设计一个项目,而这个项目的一些业务功能,需要以插件的方式提供给这个项目,从而降低耦合性,主项目不会对具体业务功能产生依赖. 在以前,最简单粗暴的方式,就是扫描主程序目录下的所有dll或指定目录下的dll,然

vue + elementui 中的弹窗组件封装成公共组件

如果一个弹窗比较简单,可以直接放在页面中,通过visible属性的true,false控制显示隐藏就可以了,我们今天要说的是将个比较复杂的弹窗组件封装成全局组件,然后可以在项目中的任何一个页面引用~~下面走起 1.首先要注册个全局组件,用下面的全局API  Vue.component('my-component', { /* ... */ }) 在js文件中首先引入这个弹窗组件,组件名称是iesPersonRadioDialog,项目中会引入一个js文件,这个js文件中在分别引入其他的js,模块