给定一个像这样的过滤器:
class MyFilter(django_filters.rest_framework.FilterSet):
include_unusual_entries = django_filters.BooleanFilter(method='noop')
我希望'默认'查询集
MyModel.objects.exclude(unusual_state=True)
并且只有设置了include_unusual_entries
过滤器时,我希望查询集为
MyModel.objects.all()
我错过了解决这个问题的明显方法吗?我没有看到在过滤器上设置invert=True
的方法,或设置always_filter
的方法,以便我可以将{0}放入method
。
现在,我通过覆盖我的过滤器集上的qs
属性来解决它,但感觉非常错误:
@property
def qs(self):
queryset = super(MyFilter, self).qs
if 'include_unusual_entries' in self.data: # if inclusion is explcitly enabled
return queryset
else: # if inclusion is *not* explicitly enabled (the default)
return queryset.exclude(unusual_state=True)
答案 0 :(得分:1)
我在下面留下了我原来的答案,但更简单的选择是将method
和CheckboxInput
结合起来,这不区分空和假。实际上,除非另有说明,否则默认为false。这是CheckboxInput
实际上适合的少数几个实例之一。
class MyFilter(filters.FilterSet):
include_unusual_entries = filters.BooleanFilter(
method='filter_unusual_entries',
widget=forms.CheckboxInput,
)
def filter_unusual_entries(self, qs, name, value):
return qs if value else qs.exclude(unusual_state=True)
这是一个不寻常的案例。过滤通常是一个减法过程,但这里它是附加的。虽然您当前的解决方案可能会感到笨拙,但确实如此
有效。我要做的唯一更改是从表单cleaned_data
中提取值而不是从未处理的data
查询字典中提取值。
if self.cleaned_data.get('include_unusual_entries', False):
return queryset
那说,一些替代解决方案:
from django_filters import rest_framework as filters
from django_filters.constants import EMPTY_VALUES
class MyFilter(filters.FilterSet):
include_unusual_entries = filters.BooleanFilter(method='filter_unusual_entries')
def __init__(self, data=None, *args, **kwargs):
if data is not None: # if filterset is bound, force default value
data = data.copy() # get a mutable copy of the QueryDict
if data.get('include_unusual_entries', None) in EMPTY_VALUES:
data['include_unusual_entries'] = False
super().__init__(data, *args, **kargs)
def filter_unusual_entries(self, name, qs, value):
return qs if value else qs.exclude(unusual_state=True)
filter_queryset()
覆盖.qs
属性一直有点尴尬。虽然它仍处于开发阶段,但django-filter 2.x解决了这个问题。您可以覆盖filter_queryset()
。
from django_filters import rest_framework as filters
from django_filters.constants import EMPTY_VALUES
class MyFilter(filters.FilterSet):
include_unusual_entries = filters.BooleanFilter(method='noop')
def filter_queryset(self, queryset):
if not self.form.cleaned_data.get('include_unusual_entries', False):
queryset = queryset.exclude(unusual_state=True)
return super().filter_queryset(queryset)