Django REST框架中的否定或排除过滤器

8 投票
4 回答
12994 浏览
提问于 2025-04-18 03:40

我已经使用Django REST框架一段时间了,但遇到了一种情况,我需要在API视图中获取所有内容,但要排除一个已知的关系。经过再次查看文档,我发现没有内置的方法可以做到这一点。我知道我可以在我的ListView中重写get_queryset(),解析自定义的URL查询参数,然后进行过滤,但我很好奇有没有人有更优雅的解决方案?

更新

经过进一步研究,这似乎更像是一个关于django-filter的问题,我找不到任何排除功能的提及。不过我找到了一些东西:

https://bitbucket.org/mjs7231/django-rest-framework-filtering

这个链接提供了从结果中排除值的功能。

4 个回答

0

你可以这样在查询结果上加条件:

# Default queryset
queryset = MyModel.objects.all()

# FILTERING
# Get all query parameters from the request
query_params = request.query_params

# Iterate over all parameters and apply filters
for param, value in query_params.items():
   try:
       if "!" not in value:
           queryset_tmp = queryset.filter(**{param: value})
       else:
           value_to_exclude = value.split('!')[1]
           queryset_tmp = queryset.exclude(**{param: value_to_exclude})
   except:
       queryset_tmp = queryset
   queryset = queryset_tmp

这样做的话,你只需要在想要排除的值前面加一个"!"。比如说:/this/example/filter?status=!done

2

你可以使用 django-rest-framework-filters 这个工具包。它支持在查询字符串中使用排除的语法,也就是 key!=value 的形式。

举个例子,/api/search?name!=Alex 这个意思是搜索名字不是 Alex 的结果。

11

在你的过滤器设置中,使用 exclude 参数来定义过滤器。

class MyFilterSet(FilterSet):
    negated_field__not = django_filters.NumberFilter(field_name='negated_field', exclude=True)

    class Meta:
        model = Model
        fields = ['some_field', 'some_other_field']

class MyViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Model.objects.all()
    serializer_class = SomeSerializer

    filter_backends = (DjangoFilterBackend,)
    filter_class = MyFilterSet

这就相当于 Model.objects.all().exclude(negated_field__exact=value)。然后,从你的前端页面,你可以排除请求像这样的 URL: /api/my_viewset/?negated_field__not=value

4

听起来你是在寻找自定义过滤后端

撰写回答