我有一个视图集,需要通过参数灵活排序和按参数过滤自定义list()
覆盖。我能够通过django-filter
获得订购以及过滤各种参数,但我不能让它们同时起作用。
这是我的简化views.py
代码,用于排序结果:
class AssetViewSet(viewsets.GenericViewSet, AssetPaginationMixin,):
queryset = Asset.objects.all()
pagination_class = AssetPagination
serializer_class = serializers.AssetSerializer
filter_backends = (OrderingFilter, )
ordering_fields = ('id', 'session_id')
filter_class = AssetFilterSet
def list(self, request):
assets = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(assets, many=True)
return Response(serializer.data)
以下是适用于过滤的代码:
class AssetViewSet(viewsets.GenericViewSet, AssetPaginationMixin,):
queryset = Asset.objects.all()
pagination_class = AssetPagination
serializer_class = serializers.AssetSerializer
filter_backends = (OrderingFilter, )
ordering_fields = ('id', 'session_id')
filter_class = AssetFilterSet
def list(self, request):
assets = AssetFilterSet(request.query_params)
serializer = self.get_serializer(assets, many=True)
return Response(serializer.data)
最后,我的filters.py
代码:
class AssetFilterSet(django_filters.FilterSet):
project_id = django_filters.NumberFilter()
submitted = django_filters.TypedChoiceFilter(choices=BOOLEAN_CHOICES, coerce=strtobool)
class Meta:
model = Asset
fields = ['project',
'submitted']
唯一的区别是list()
的第一行。出于某种原因,似乎AssetFilterSet
需要直接应用于list()
才能生效,否则如果我在self.filter_queryset
中使用list()
,尽管被filter_class = AssetFilterSet
指定,则需要绕过它。
我会回答我自己的问题。事实证明这是一个非常简单的修复;尽管在SETTINGS中全局指定了DjangoFilterBackend
,你必须明确包括OrderingFilter
和filter_backends
作为DjangoFilterBackend
。
这是工作代码:
class AssetViewSet(viewsets.GenericViewSet, AssetPaginationMixin,):
queryset = Asset.objects.all()
pagination_class = AssetPagination
serializer_class = serializers.AssetSerializer
filter_backends = (DjangoFilterBackend, OrderingFilter,)
ordering_fields = ('id', 'session_id')
filter_class = AssetFilterSet
def list(self, request):
assets = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(assets, many=True)
return Response(serializer.data)
我的印象是在SETTINGS中指定DjangoFilterBackend
意味着默认情况下会包含它,并且添加一个filter_backends
过滤器会添加它,而不是替换它。活到老,学到老!