• Django系列之DRF搜索和过滤


    1. model之间关系

    class Publish(models.Model):
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=8)
        email = models.CharField(max_length=32)
    
    class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        pub_date = models.DateField()
        publish = models.ForeignKey(Publish, on_delete=models.CASCADE, null=True)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2. DRF搜索

    在DRF中使用搜索功能,只需要在 viewsets 视图类中定义 filter_backendssearch_fields 即可使用。

    filter_backends:后端使用的搜索和过滤类。
    search_fields :要执行搜索条件的字段,搜索为模糊查询(要在哪些字段上执行模糊查询,支持多表连表查询)。
    对应的URL格式就是这种:http://127.0.0.1:9000/test/publishes/?search=北京

    class PublishModelViewSets(viewsets.ModelViewSet):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
        filter_backends = (SearchFilter, )
        search_fields = ("name", "city", "book__title")   
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3. django-filter简单过滤

    安装包:pip install django-filter
    使用:在 viewsets 视图类的 filter_backends 属性中追加 DjangoFilterBackend,再添加 filterset_fields 属性即可使用。

    filterset_fields:要执行过滤条件的字段,执行的是精准查询。
    对应的URL格式就是这种 http://127.0.0.1:9000/test/publishes/?name=GansuEngEduPublisher&city=甘肃

    在settings配置文件的app中添加:

    INSTALLED_APPS = [
    	...
        'django_filters'
    ]
    
    • 1
    • 2
    • 3
    • 4
    class PublishModelViewSets(viewsets.ModelViewSet):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
        filter_backends = (SearchFilter, DjangoFilterBackend)
        search_fields = ("name", "city", "book__title")     # 模糊查询
        filterset_fields = ("name", "city")					# 精准查询
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    filterset_fields 也可以按照自定义的方式过滤。
    对应的URL格式就是这种:http://127.0.0.1:9000/test/publishes/?name__icontains=gansueng&city=甘肃

    class PublishModelViewSets(viewsets.ModelViewSet):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
        filter_backends = (SearchFilter, DjangoFilterBackend)
        search_fields = ("name", "city", "book__title")     # 模糊查询
        filterset_fields = {
            "name": ["icontains"],      # 包含此查询条件,大小写不敏感
            "city": ['exact']           # 完全相等
        }
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4. django-filter自定义过滤器类和过滤器函数

    • 过滤器中常用的字段类型,这些类型要和模型中对应的字段类型兼容:
    CharFilter         字符串类型
    BooleanFilter      布尔类型
    DateTimeFilter     日期时间类型
    DateFilter         日期类型
    DateRangeFilter    日期范围
    TimeFilter         时间类型
    NumberFilter       数值类型,对应模型中IntegerField, FloatField, DecimalField
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 字段内参数说明:
    field_name:过滤字段名,对应模型中的字段名
    lookup_expr:查询时所要进行的操作,和ORM中运算符一致
    method:该字段对应的自定义过滤器函数
    
    • 1
    • 2
    • 3
    • Meta字段使用:
    model:引用的模型,不是字符串
    fields:指明过滤字段,可以是列表,列表中字典可以过滤,默认是判断相等;也可以是字典,字典可以自定义操作。
    exclude:排除字段,不允许使用列表中字典进行过滤
    
    • 1
    • 2
    • 3

    5. django-filter 使用示例

    在视图类中添加自定义的过滤类:

    class PublishModelViewSets(viewsets.ModelViewSet):
        queryset = Publish.objects.all()
        serializer_class = PublishSerializer
        filter_backends = (SearchFilter, DjangoFilterBackend)
        search_fields = ("name", "city", "book__title")   
        filter_class = PublishFilter		# 自定义过滤类
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在app中新建一个filters.py文件,编写自己的自定义过滤函数,也可以不写,使用默认的 orm 筛选关键字。

    from django_filters import filters, FilterSet
    from app01.models import Publish
    
    class PublishFilter(FilterSet):
        pub_city = filters.CharFilter(field_name='city', lookup_expr='exact')
        pub_email = filters.CharFilter(field_name='email', method='filter_email')
    
        @staticmethod
        def filter_email(queryset, field_name, value):
            """
            出版社邮件以前端传过来的value值结尾的出版社
            :param queryset: 查询到的数据集
            :param field_name: 过滤的字段名
            :param value: 前端传过来的值
            :return: 过滤后的数据集
            """
            print(field_name, value)
            return queryset.filter(**{f"{field_name}__endswith": value})
    
        class Meta:
            model = Publish     # 模型名
            fields = ["pub_city", "pub_email"]         # 过滤字段
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    对应的URL格式就是这样:http://127.0.0.1:9000/test/publishes/?pub_city=北京&pub_email=edu

    注意:上述的自定义过滤器类和过滤器函数的方式,在 django-filter 的某些版本不适用,会导致无法过滤,获取到的是全集。上述使用的 django-filter 版本为 21.1。

  • 相关阅读:
    STM8的C语言编程(1)--基本程序与启动代码分析
    【U8+】用友U8成本管理模块下,定额分配标准中无法取到新增存货的数据。
    Mqtt 客户端 java API 教程
    哈工大李治军老师操作系统笔记【8】:用户级线程(Learning OS Concepts By Coding Them !)
    JVM运行时数据区
    Css框架之星星评价功能
    数字图像基础
    .net 奇葩问题调试经历之2——内存暴涨,来自非托管的内存泄露
    k8s master 是如何进行pod的调度的
    Hive之同比环比的计算
  • 原文地址:https://blog.csdn.net/CSDN1csdn1/article/details/133970691