zoukankan      html  css  js  c++  java
  • 10)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
    View Code
    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()),

    1.drf  搜索 过滤组件

    views.py
    from rest_framework.generics import ListAPIView
    ​
    # 第一步:drf的SearchFilter - 搜索过滤
    from rest_framework.filters import SearchFilter
    ​
    class CarListAPIView(ListAPIView):
        queryset = models.Car.objects  # 固定的两个东西,源码内部默认为Noen
        serializer_class = serializers.CarModelSerializer
    ​
        # 第二步:局部配置 过滤类 们(全局配置用DEFAULT_FILTER_BACKENDS)
        filter_backends = [SearchFilter]
    ​
        # 第三步:SearchFilter过滤类依赖的过滤条件 => 接口:/cars/?search=...
        search_fields = ['name', 'price']
        # eg:/cars/?search=1,name和price中包含1的数据都会被查询出

    2. drf  排序  过滤组件

    views.py
    from rest_framework.generics import ListAPIView
    ​
    # 第一步:drf的OrderingFilter - 排序过滤
    from rest_framework.filters import OrderingFilter
    ​
    class CarListAPIView(ListAPIView):
        queryset = models.Car.objects
        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升序

    3. drf  基础分页组件

    api / pahenations.py
    from rest_framework.pagination import PageNumberPagination
    ​
    class MyPageNumberPagination(PageNumberPagination):
        # ?page=1,这个就是url中的key,
        page_query_param = 'page'
    # ?page=1 不传自定义条数时默认一页显示的条数,可以通过下面的参数设置自定义 page_size = 3 # ?page=2&page_size=3 第二页每页显示3条数据 用户自定义一页显示的条数 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(),不然分页会出问题,上面搜索和排序不需要all是因为人家已经过滤过了
        queryset = models.Car.objects.all()
        serializer_class = serializers.CarModelSerializer
        
        # 分页组件 - 给视图类配置分页类即可 - 分页类需要自定义,继承drf提供的分页类即可
        pagination_class = pagenations.MyPageNumberPagination

    4. drf 偏移分页组件

    pahenations.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可以实现排行前几或后几,后面我们会自定义limit过滤器就不需要基于分页了
        # ?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

    5. drf游标分页组件(了解)

    pahenations.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'  # 按照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

    6. 自定义 limit 过滤器

    我不想借助分页,我就想自定义一个条数过滤器,他可以对各过滤组件过滤结果进行显示限制

    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
        # eg:/cars/?ordering=-price,pk&limit=3,先按price降序,如果出现price相同,再按pk升序,筛选结果显示3条
    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

    安装
    >: pip3 install django-filter
    过滤条件层:自定义api/filters.py
    # django-filter插件过滤器类
    from django_filters.rest_framework.filterset import FilterSet
    from . import models
    ​
    # 自定义过滤字段
    from django_filters import filters
    class CarFilterSet(FilterSet): min_price = filters.NumberFilter(field_name='price', lookup_expr='gte') # gte lte 源码里面有,表示最大最小值 max_price = filters.NumberFilter(field_name='price', lookup_expr='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间的宝马牌汽车

       
       

     

     

  • 相关阅读:
    BZOJ 2400: Spoj 839 Optimal Marks (按位最小割)
    bzoj4873: [Shoi2017]寿司餐厅(最大权闭合子图)
    bzoj1497: [NOI2006]最大获利(最大权闭合子图)
    bzoj1607: [Usaco2008 Dec]Patting Heads 轻拍牛头
    bzoj1024: [SCOI2009]生日快乐
    bzoj2761: [JLOI2011]不重复数字
    bzoj1257: [CQOI2007]余数之和sum
    bzoj2456: mode
    bzoj1831: [AHOI2008]逆序对(DP+双精bzoj1786)
    bzoj2431: [HAOI2009]逆序对数列
  • 原文地址:https://www.cnblogs.com/xp1315458571/p/11735728.html
Copyright © 2011-2022 走看看