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间的宝马牌汽车
        
    
  • 相关阅读:
    Proj THUDBFuzz Paper Reading: The Art, Science, and Engineering of Fuzzing: A Survey
    Proj THUDBFuzz Paper Reading: A systematic review of fuzzing based on machine learning techniques
    9.3 付费代理的使用
    11.1 Charles 的使用
    第十一章 APP 的爬取
    10.2 Cookies 池的搭建
    10.1 模拟登录并爬取 GitHub
    11.5 Appium 爬取微信朋友圈
    11.4 Appium 的基本使用
    11.3 mitmdump 爬取 “得到” App 电子书信息
  • 原文地址:https://www.cnblogs.com/demiao/p/11986303.html
Copyright © 2011-2022 走看看