Как отфильтровать значения двух полей как одно?

Как объединить результаты двух полей и показать их как одно в django-filter?

Возьмем, к примеру, такую ​​модель:

class Animal(object):
     LEGS_CHOICES = (2, 4, 8)
     legs = models.PositiveSmallIntegerField(choices=LEGS_CHOICES)

class Dog(Animal):
     pass

class Spider(Animal):
     pass

Мой класс фильтра django-filter:

class AnimalFilterSet(django_filters.FilterSet):
    legs = django_filters.MultipleChoiceFilter(choices=Animal.LEGS_CHOICES, widget=forms.CheckboxSelectMultiple())

    class Meta:
        model = Animal
        fields = ['legs']

Я хотел бы отфильтровать эти две модели по одним и тем же полям и отобразить их как одну.

Используя набор запросов, я могу сделать это следующим образом:

Animal.objects.filter(Q(dog__legs = 4) | Q(spider__legs = 4))

person bns    schedule 25.11.2014    source источник


Ответы (1)


Я написал свой собственный фильтр

class MultiMultipleChoiceFilter(django_filters.Filter):
    """
    This filter preforms an OR query on the selected options for defined fields.
    """
    field_class = forms.MultipleChoiceField

    def __init__(self, fields, *args, **kwargs):
        super(MultiMultipleChoiceFilter, self).__init__(*args, **kwargs)
        self.fields = fields

    def filter(self, qs, value):
        value = value or ()
        if len(value) == len(self.field.choices):
            return qs
        q = Q()
        for v in value:
            for f in self.fields:
                q |= Q(**{f: v})
        return qs.filter(q).distinct()

Пример использования. В качестве параметра введите список полей.

class AnimalFilterSet(django_filters.FilterSet):
    legs = django_filters.MultiMultipleChoiceFilter(['dog__legs', 'spider__legs'], choices=Animal.LEGS_CHOICES, widget=forms.CheckboxSelectMultiple())

    class Meta:
        model = Animal
        fields = ['legs']
person bns    schedule 26.11.2014
comment
Это мне очень помогло, спасибо. Однако в django-filter v.1.0.4 метка формы отображалась как [недопустимое поле] на странице, если только я не включил явную опцию «метка» в определение поля в классе FilterSet. - person user1255933; 16.12.2017