使用Django过滤器的{OR}逻辑

时间:2016-04-09 12:57:54

标签: python django django-filter

我正在使用Django-filter来允许用户根据两个字段中的多个选项过滤数据库。 filterset.py看起来像这样:

class TapFilter(django_filters.FilterSet):
bar__region = django_filters.MultipleChoiceFilter(choices=CHOICES, label="Regions:", widget=forms.CheckboxSelectMultiple,help_text="")
bar = django_filters.ModelMultipleChoiceFilter(queryset=Bar.objects.all(), label="Bars:", widget=forms.CheckboxSelectMultiple,help_text="")

但是,它在两个列表之间用作AND。我需要OR而不是。也就是说,我需要在任一类别中显示与选择相匹配的任何内容。

我已经看到使用普通过滤器的类似问题,但我更愿意继续使用django-filter。

相关网站位于:http://bestap.pythonanywhere.com/

更新:我把它放在我的filtersets.py中,但我显然做得不对......

class TapFilter(django_filters.FilterSet):
    bar__region = django_filters.MultipleChoiceFilter(choices=CHOICES, label="Regions:", widget=forms.CheckboxSelectMultiple,help_text="")
    bar = django_filters.ModelMultipleChoiceFilter(queryset=Bar.objects.all(), label="Bars:", widget=forms.CheckboxSelectMultiple,help_text="")
    def qs(self):
        base_qs = Bar.objects.all()
        qs = Bar.objects.none()
        for name, filter_ in six.iteritems(self.filters):
            value = self.form.cleaned_data[name]
            qs = qs | filter_.filter(base_qs, value)
        return qs

这给了我错误'function'对象没有属性'count'。

1 个答案:

答案 0 :(得分:1)

您需要覆盖qs TapFilter子类的FilterSet

base implementation is not that complicated; essence of it loops over the filters applying them to the queryset

简化为:

for name, filter_ in six.iteritems(self.filters):
    value = self.form.cleaned_data[name]
    qs = filter_.filter(qs, value)

你需要结合过滤器的QuerySets,你可以得到QuerySet implements __or__,所以(再次简化)你需要这样的东西:

base_qs = Bar.objects.all()
qs = Bar.objects.none()
for name, filter_ in six.iteritems(self.filters):
    value = self.form.cleaned_data[name]
    qs = qs | filter_.filter(base_qs, value)

希望这能让你开始。