zoukankan      html  css  js  c++  java
  • drf-过滤组件|分页组件|过滤器

    drf-过滤组件|分页组件|过滤器

    群查接口各种筛选组件数据准备

    models.py
    class Car(models.Model):
        name = models.CharField(max_length=16, unique=True, verbose_name='车名')
        price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='价格')
        brand = models.CharField(max_length=16, verbose_name='品牌')
    
        class Meta:
            db_table = 'api_car'
            verbose_name = '汽车表'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    admin.py
    admin.site.register(models.Car)
    
    serializers.py
    class CarModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Car
            # 参与序列化的字段
            fields = ['name', 'price', 'brand']
    
    views.py
    # Car的群查接口
    from rest_framework.generics import ListAPIView
    
    class CarListAPIView(ListAPIView):
        queryset = models.Car.objects.all()
        serializer_class = serializers.CarModelSerializer
    
    urls.py
    url(r'^cars/$', views.CarListAPIView.as_view()),
    

    drf过滤组件

    搜索过滤组件 | SearchFilter

    使用步骤:
    1.导入搜索过滤器 SearchFilter
    2.局部配置 filter_backends = [SearchFilter]
    3.局部配置过滤类依赖的过滤条件(字段) search_fields = ['name', 'price'] 注意:依赖的过滤字段只能配置序列化类中fields里配置的字段
    接口使用样式:
    /cars/?search=...
    # eg:/cars/?search=1,name和price中包含1的数据都会被查询出
    

    案例:

    views.py
    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的数据都会被查询出
    

    排序过滤组件 | OrderingFilter

    使用步骤:
    1.导入搜索过滤 OrderingFilter
    2.局部配置 filter_backends = [OrderingFilter]
    3.局部配置过滤类依赖的过滤条件(字段) ordering_fields = ['pk', 'price']
    接口使用样式:
    /cars/?ordering=...
    # eg:/cars/?ordering=-price,pk,先按price降序,如果出现price相同,再按pk升序
    

    案例:

    views.py
    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升序
    

    drf分页组件

    自定义分页组件:

    1.pagination.py中自定义分页类(基础分页类/偏移分页类/游标分页类)
    2.视图类中配置自定义的分页类: pagination_class = 自定义分页类
    

    基础分页组件

    pagination.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
    

    偏移分页组件

    pagination.py
    from rest_framework.pagination import LimitOffsetPagination
    class MyLimitOffsetPagination(LimitOffsetPagination):
        # ?offset=从头偏移的条数&limit=要显示的条数
        limit_query_param = 'limit'
        offset_query_param = 'offset'
        
        # ?不传offset和limit默认显示前3条,只设置offset就是从偏移位往后再显示3条
        default_limit = 3
        
        # ?limit可以自定义一页显示的最大条数
        max_limit = 5
    
        # 只使用limit结合ordering可以实现排行前几或后几
        # eg: ?ordering=-price&limit=2  => 价格前2
    
    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.MyLimitOffsetPagination
    

    游标分页组件

    pagination.py
    # 注:必须基于排序规则下进行分页
    # 1)如果接口配置了OrderingFilter过滤器,那么url中必须传ordering
    # 1)如果接口没有配置OrderingFilter过滤器,一定要在分页类中声明ordering按某个字段进行默认排序
    from rest_framework.pagination import CursorPagination
    class MyCursorPagination(CursorPagination):
        cursor_query_param = 'cursor'
        page_size = 3
        page_size_query_param = 'page_size'
        max_page_size = 5
        ordering = '-pk'
    
    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.MyCursorPagination
    

    自定义过滤类

    源码:

    class GenericAPIView(views.APIView):
        ...
        # 配置过滤器路径
        filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
        ...
        
        def filter_queryset(self, queryset):
            # 若自己的视图列中配置了filter_backends=[过滤类] 就走视图类中的
            for backend in list(self.filter_backends):
                # 当时视图类中配置了filter_backends=[过滤类]
                # 下面这步会调用我们自己定义的过滤类的filter_queryset方法
                queryset = backend().filter_queryset(self.request, queryset, self)
            return queryset
    

    使用:

    # 1.自定义过滤类,重写filter_queryset方法
    # 2.在视图类中配置filter_backends = [自定义过滤类]补充: 自定义过滤类不需要继承GenericAPIView,因为视图类继承了ListAPIView, ListAPIView本来就继承GenericAPIView我们自定义的过滤类要在视图类中配置,当源码中的GenericAPIView要调用过滤类时就会调用我们在视图类中配置的自定义过滤类,从而调用filter_query方法
    

    filters.py

    class LimitFilter:
        # 重写filter_queryset方法
        def filter_queryset(self, request, queryset, view):
            # 从get请求中获取limit的值
            limit_mun = request.query_params.get('limit')
            if limit_mun:
                limit_mun = int(limit_mun)
                # 将queryset列表按limit_num切分
                return queryset[:limit_mun]
            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]
    

    过滤器插件:django-filter

    安装
    >: pip3 install django-filter
    
    过滤条件层:自定义api/filters.py
    from django_filters.rest_framework.filterset import FilterSet
    from . import models
    from django_filters import filters
    
    class CarFilterSet(FilterSet):
        # 自定义过滤字段
        max_price = filters.NumberFilter(
            field_name='price',  # 该自定义字段关联的model类表中的字段
            lookup_expr='gte',  # 查找的条件  'gte':大于等于
        )
        min_price = filters.NumberFilter(
            field_name='price',  # 该自定义字段关联的model类表中的字段
            lookup_expr='lte',  # 查找的条件  'lte':小于等于
        )
        class Meta:
            model = models.Car
            fields = ['brand', 'min_price', 'max_price']
            # brand是model中存在的字段,一般都是可以用于分组的字段
            # min_price、max_price是自定义字段,需要自己自定义过滤条件
    

    视图层:views.py

    # django-filter插件过滤器
    from django_filters.rest_framework import DjangoFilterBackend
    from .filters import CarFilterSet
    
    class CarListAPIView(ListAPIView):
        queryset = models.Car.objects.all()
        serializer_class = serializers.CarModelSerializer
        
        # 局部配置 过滤类 们(全局配置用DEFAULT_FILTER_BACKENDS)
        filter_backends = [DjangoFilterBackend]
        
        # django-filter过滤器插件使用
        filter_class = CarFilterSet
        # 接口:?brand=...&min_price=...&max_price=...
        # eg:?brand=宝马&min_price=5&max_price=10 => 5~10间的宝马牌汽车
        
    
  • 相关阅读:
    使用环信WebIm实现一个客服功能
    html中的下拉框—select和input方式
    [LeetCode] 206. Reverse Linked List
    visual studio 2019安装配置可编写c/c++语言的IDE环境
    JS判断数据类型是不是undefined
    idea微服务架构出现 Run Dashboard 按钮方法
    docker 常用命令
    配置docker镜像加速
    linux安装docker
    linux安装redis
  • 原文地址:https://www.cnblogs.com/demiao/p/11986303.html
Copyright © 2011-2022 走看看