如何通过多个关键字从数据库中过滤DRF中的数据?

How to filter data in DRF from database by multiple keywords?

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

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

我正在尝试使用 django_filters

这里如果过滤器class:

# filter

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

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

这里如果视图class:

# 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

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

我想你可以这样做:

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

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

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

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 模板中使用此过滤器集时,您需要以逗号分隔格式输入您的值,如下所示:

在我的例子中,我需要按多个关键字进行过滤,然后从过滤的 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']
        }