如何通过多个关键字从数据库中过滤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
但在这种情况下,它只过滤我在表格中输入的一个词。
我想你可以这样做:
首先,从 BaseInFilter 和 CharFilter
创建一个新的过滤器集 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']
}
我是初学者,我用 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
但在这种情况下,它只过滤我在表格中输入的一个词。
我想你可以这样做:
首先,从 BaseInFilter 和 CharFilter
创建一个新的过滤器集 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']
}