【问题标题】:How to filter data in DRF from database by multiple keywords?如何通过多个关键字从数据库中过滤 DRF 中的数据?
【发布时间】:2019-09-29 12:15:17
【问题描述】:

我是一个初学者,使用 Django REST 框架开发了一个小的 REST API 项目。 PostgreSQL 数据库中有一堆带有文本字段的记录,我有一些关键字列表。我正在尝试过滤包含此文本字段中我的一个或一些关键字列表中的单词的数据。

您能否建议我另一种方式来组织 DRF 中的过滤,即一次使用整个关键字列表而不在表单中输入它们?

我正在尝试使用 django_filters 来实现

这里 if 过滤器类:

# filter

class DataFilter(django_filters.rest_framework.FilterSet):
    keyword = CharFilter(field_name='description', lookup_expr='icontains')

    class Meta:
        model = Data
        fields = ('keyword', )

这里如果查看类:

# view

class DataList(generics.ListAPIView): 

    def get_queryset(self):
        return Data.objects.filter(deadline__gte=date.today())

    serializer_class = DataSerializer   
    filter_backends = (filters.DjangoFilterBackend,)
    filterset_class = DataFilter

但在这种情况下,它只过滤我在表单中输入的一个词。

【问题讨论】:

  • 嗨,伊万!非常感谢。但不幸的是,它不起作用 - 空结果(
  • 嗨,@caravan4eg 你试过下面给出的答案吗:)?你遇到过什么问题吗?
  • 嗨,@ruddra!是的,我做到了)但是,我仍然遇到了麻烦。伊万的建议必须有效,但在我的情况下,它不会过滤并且什么也不返回(

标签: python django django-rest-framework django-filter


【解决方案1】:

我认为你可以这样做:

首先,从BaseInFilterCharFilter 创建一个新的过滤器集子类:

class CharInFilter(django_filters.BaseInFilter, django_filters.CharFilter):
    pass

然后,像这样更新您的 FilterSet 类:

class DataFilter(django_filters.FilterSet):
    keyword__in = CharInFilter(field_name='keyword', lookup_expr='in')

    class Meta:
        model = Data
        fields = []

然后你可以像这样使用这个FilterSet(与你当前的实现相同):

class DataList(generics.ListAPIView): 

    def get_queryset(self):
        return Data.objects.filter(deadline__gte=date.today())

    serializer_class = DataSerializer   
    filter_backends = (filters.DjangoFilterBackend,)
    filterset_class = DataFilter

在 DRF 模板中使用此过滤器集时,您需要以逗号分隔格式输入值,如下所示:

【讨论】:

    【解决方案2】:

    就我而言,我需要按多个关键字进行过滤,然后从过滤后的 qs 中排除另一组关键字。 类似base_url/?kwords=kw1,kw2,kw3&exclude=e_kw1,e_kw2&others....

    filters.BaseInFilter 继承对我不起作用......这很奇怪,因为 BaseInFilter 继承自 BaseCSVFilter,或者我犯了一个错误。

    我的解决方案:

    from django.db.models import Q
    from django_filters import rest_framework as filters
    from products.models import Product
    
    
    class KwordIncludeFilter(filters.BaseCSVFilter):
    
        def filter(self, qs, values):
            query = Q()
            if not values:
                return qs
            else:
                for value in values:
                    value = value.strip()
                    query |= Q(name__icontains=value)
                    qs = qs.filter(query)
                return qs
    
    
    class KwordExcludeFilter(filters.BaseCSVFilter):
    
        def filter(self, qs, values):
            query = Q()
            if not values:
                return qs
            else:
                for value in values:
                    value = value.strip()
                    query |= Q(name__icontains=value)
                    qs = qs.exclude(query)
                return qs
    
    
    class ProductFilter(filters.FilterSet):
    
        kwords = KwordIncludeFilter()
        exclude = KwordExcludeFilter()
    
        class Meta:
            model = Product
            fields = {
                'some_other_model_filed': ['some_lookup']
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-07
      • 2021-07-04
      • 2015-10-14
      • 2014-10-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多