• drf--搜索、过滤、排序组件


    drf--搜索、过滤、排序组件

    过滤

    DjangoFilterBackend

    默认情况下 DRF generic list view 会返回整个 queryset查询结果,但通常业务只是需要其中一部分,这种情况下就需要使用 "过滤器" 来限制返回结果集。
    最笨的方式是继承GenericAPIView类或使用继承了GenericAPIView的类,然后重写.get_queryset() 方法 ,首先我们看类视图中增加一个方法get_queryset

    from rest_framework import generics
    class ArticleViewSet(generics.ListAPIView):
        queryset = Article.objects.all()  # 查询结果集
        serializer_class = ArticleSerializer # 序列化类
        pagination_class = ArticlePagination   # 自定义分页会覆盖settings全局配置的
    
        def get_queryset(self):
            queryset = Article.objects.all()
            read_num = self.request.query_params.get('read_num', 0)  # 获取查询字段值
            if read_num:
                queryset = queryset.filter(read_num__gt=int(read_num))
    
            return queryset
    

    通过重写get_queryset方法来达到过滤效果,这样做如果在过滤条件复杂的情况下,代码会显得过于冗余,而且有可能大部分代码一直在重复实现类似的功能,在日常操作中,我们需要获取指定条件的数据,例如对于文章,我们需要指定分类、浏览数、点赞数等。有时候我们需要按照浏览数进行排序。这些都需要我们对ArticleViewSet进行更多的拓展。

    自定义过滤器django-filter模块

    django-filter`库包括一个`DjangoFilterBackend`类,它支持`REST`框架的高度可定制的字段过滤。
     首先安装`django-filter
    pip install django-filter
    

    然后将django_filters添加到DjangoINSTALLED_APPS

    REST_FRAMEWORK = {
        'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
    }
    

    或者将过滤器加到单个View或ViewSet中(一般使用这种):

    from rest_framework import viewsets
    from django_filters.rest_framework import DjangoFilterBackend
    
    class ArticleViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
        queryset = Article.objects.all()  # 查询结果集
        serializer_class = ArticleSerializer # 序列化类
        pagination_class = ArticlePagination   # 自定义分页会覆盖settings全局配置的
        # 过滤器
        filter_backends = (DjangoFilterBackend,)
        # 如果要允许对某些字段进行过滤,可以使用filter_fields属性。
        filter_fields = ('title', 'category')
    
        # def get_queryset(self):
        #     queryset = Article.objects.all()
        #     read_num = self.request.query_params.get('read_num', 0)
        #
        #     if read_num:
        #         queryset = queryset.filter(read_num__gt=int(read_num))
        #
        #     return queryset
    

    可以看出通过加过滤器和添加对应字段会过滤相关的,注意这里是精确匹配,字段间是且的关系,若一个为空,则按照其他的匹配,比如title=测试&category=则按照title来精确查找。

    自定义过滤类

    默认是按照精准匹配,若想达到模糊搜索,可以自定义过滤类,再用filter_class指定过滤集合类。
    新建过滤文件filters.py

    from django_filters import rest_framework
    from article.models import Article
    
    class AriticleFilter(rest_framework.FilterSet):
        min_read = rest_framework.NumberFilter(field_name='read_num', lookup_expr='gte')
        max_read = rest_framework.NumberFilter(field_name='read_num', lookup_expr='lte')
        title = rest_framework.CharFilter(field_name='title', lookup_expr='icontains')
    
        class Meta:
            model = Article
            fields = ['title', 'category', 'min_read', 'max_read']
    

    将视图类修改

    from rest_framework import viewsets
    from django_filters.rest_framework import DjangoFilterBackend
    from .filters import AriticleFilter
    
    class ArticleViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
        queryset = Article.objects.all()  # 查询结果集
        serializer_class = ArticleSerializer # 序列化类
        pagination_class = ArticlePagination   # 自定义分页会覆盖settings全局配置的
        # 过滤器
        filter_backends = (DjangoFilterBackend,)
        # 如果要允许对某些字段进行过滤,可以使用filter_fields属性。
        #filter_fields = ('title', 'category')
        # 使用自定义过滤器
        filter_class = AriticleFilter
    
    

    搜索SearchFilter

    如果要明确指定可以对哪些字段进行搜索,可以使用search_fields属性,默认为可以对serializer_class属性指定的串行器上的任何可读字段进行搜索:

    from rest_framework import viewsets
    from django_filters.rest_framework import DjangoFilterBackend
    from rest_framework import filters
    
    from .filters import AriticleFilter
    
    class ArticleViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
        queryset = Article.objects.all()  # 查询结果集
        serializer_class = ArticleSerializer # 序列化类
        pagination_class = ArticlePagination   # 自定义分页会覆盖settings全局配置的
        # 过滤器
        filter_backends = (DjangoFilterBackend,filters.SearchFilter,)
        # 如果要允许对某些字段进行过滤,可以使用filter_fields属性。
        #filter_fields = ('title', 'category')
        # 使用自定义过滤器
        filter_class = AriticleFilter
        search_fields = ('title', 'description', 'content')
    

    默认情况下,搜索将使用不区分大小写的部分匹配。 搜索参数可以包含多个搜索项,它们应该是空格和/或逗号分隔。 如果使用多个搜索项,则仅当所有提供的条款匹配时,才会在列表中返回对象。默认情况下,搜索参数被命名为“search”,但这可能会被SEARCH_PARAM设置覆盖。
    The search behavior may be restricted by prepending various characters to the search_fields.
    可以通过在search_fields中加入一些字符来限制搜索行为,如下:

    • '^' :以xx字符串开始搜索
    • '=' :完全匹配
    • '@' :全文搜索(目前只支持Django的MySQL后端)
    • '$' :正则表达式搜索

    如:search_fields = ('@username', '=email')

    排序OrderingFilter

    REST framework提供了对于排序的支持,使用REST framework提供的OrderingFilter过滤器后端即可。OrderingFilter过滤器要使用ordering_fields 属性来指明可以进行排序的字段有哪些。

    from rest_framework.filters import OrderingFilter
    
        # 过滤器,只针对当前查询过滤,所以不在settings.py中配置
        filter_backends = (OrderingFilter,)
        # 排序
        ordering_fields = ('create_time', 'price', 'sales')
    

    OrderingFilter 类支持对单个查询字段结果集进行排序。
    默认情况下,查询参数被命名为“ordering”,但这可能会被ORDERING_PARAM设置覆盖。
    可以使用ordering_fields属性明确指定可以对哪些字段执行排序,这有助于防止意外的数据泄露,例如允许用户对密码散列字段或其他敏感数据进行排序。
    如果不指定ordering_fields属性,则默认为可以对serializer_class属性指定的串行器上的任何可读字段进行过滤。

    from rest_framework import viewsets
    from django_filters.rest_framework import DjangoFilterBackend
    from rest_framework import filters
    from .filters import AriticleFilter
    
    class ArticleViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
        queryset = Article.objects.all()  # 查询结果集
        serializer_class = ArticleSerializer # 序列化类
        pagination_class = ArticlePagination   # 自定义分页会覆盖settings全局配置的
        # 过滤器 过滤,搜索,排序
        filter_backends = (DjangoFilterBackend,filters.SearchFilter,filters.OrderingFilter)
        # 如果要允许对某些字段进行过滤,可以使用filter_fields属性。
        #filter_fields = ('title', 'category')
        # 使用自定义过滤器
        filter_class = AriticleFilter
        # 搜索
        search_fields = ('title', 'description', 'content')
        # 排序
        ordering_fields = ('id', 'read_num')
    
  • 相关阅读:
    优化Http请求、规则1减少Http请求 更新中
    js 验证日期格式
    SQL 在OPENQUERY中使用参数
    onpropertychange 和 onchange
    js 去掉空格
    检索 COM 类工厂中 CLSID 为 {000209FF00000000C000000000000046} 的组件时失败解决方法
    C#连接oracle数据库操作
    SQL游标
    MS SQL 设置大小写区别
    vs jquery 智能提示
  • 原文地址:https://www.cnblogs.com/Hades123/p/11744180.html
Copyright © 2020-2023  润新知