Или логика с Django-фильтром


Я использую Django-фильтр, чтобы позволить пользователю фильтровать базу данных на основе нескольких вариантов в двух полях. Тот самый 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="")

Однако это функционирует как и между двумя списками. Мне нужно или вместо этого. То есть, мне нужно показать все, что соответствует выбору в любой категории.

Я видел подобные вопросы с использованием обычных фильтров, но я предпочел бы продолжать использовать django-фильтр, если это возможно.

Веб-сайт, о котором идет речь, находится здесь: 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

Это дает мне ошибку' функция ' объект не имеет атрибута 'count'.

1 3

1 ответ:

Вам нужно будет переопределить qs на вашем TapFilter FilterSet подкласс.

Базовая реализация не являетсятакой сложной ; суть ее заключается в том, что она перебирает фильтры, применяя их к queryset.

Упрощенно:

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

Вам нужно объединение запросов фильтров, которое вы можете получить, потому что QuerySet орудия труда __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)

Надеюсь, это поможет вам начать.