我已经使用 Django REST Framework 一段时间了,但遇到了一种情况,我需要检索 API 视图中除已知关系之外的所有内容。再次查看文档后,我看不到任何内置机制可以实现此目的。我意识到我可以在 ListView 中覆盖
get_queryset()
并解析自定义 URL 查询参数,然后进行过滤,但我很好奇是否还有其他人有更优雅的解决方案?
更新
经过更多研究,这似乎更多是一个 django-filter 问题,我找不到任何排除功能的提及。我确实找到了这个:
https://bitbucket.org/mjs7231/django-rest-framework-filtering
它确实提供了结果中的排除值。
在过滤器集中的过滤器定义中使用
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)
。然后,从您的前端您可以排除请求这样的网址:/api/my_viewset/?negated_field__not=value
。
听起来您正在寻找自定义过滤器后端
您可以使用django-rest-framework-filters。该包支持查询字符串 key!=value 中的排除语法。
例如,/api/search?name!=Alex
您可以对查询集应用条件,如下所示:
# 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