Ну, я пришел с решением. Это невозможно сделать с помощью обычных django-фильтров, поэтому я немного его расширил. Можно было бы улучшить это быстрое и грязное решение.
1-е добавлено пользовательское «сгруппированное» поле в django_filters.Filter и метод filter_grouped (почти копия метода filter)
class Filter(object):
def __init__(self, name=None, label=None, widget=None, action=None,
lookup_type='exact', required=False, grouped=False, **kwargs):
(...)
self.grouped = grouped
def filter_grouped(self, qs, value):
if isinstance(value, (list, tuple)):
lookup = str(value[1])
if not lookup:
lookup = 'exact' # we fallback to exact if no choice for lookup is provided
value = value[0]
else:
lookup = self.lookup_type
if value:
return {'%s__%s' % (self.name, lookup): value}
return {}
единственное отличие состоит в том, что вместо создания фильтра по набору запросов он возвращает словарь.
2-й обновленный метод / свойство BaseFilterSet qs:
class BaseFilterSet(object):
(...)
@property
def qs(self):
if not hasattr(self, '_qs'):
qs = self.queryset.all()
grouped_dict = {}
for name, filter_ in self.filters.iteritems():
try:
if self.is_bound:
data = self.form[name].data
else:
data = self.form.initial.get(name, self.form[name].field.initial)
val = self.form.fields[name].clean(data)
if filter_.grouped:
grouped_dict.update(filter_.filter_grouped(qs, val))
else:
qs = filter_.filter(qs, val)
except forms.ValidationError:
pass
if grouped_dict:
qs = qs.filter(**grouped_dict)
(...)
return self._qs
Хитрость заключается в том, чтобы хранить все «сгруппированные» фильтры в словаре, а затем использовать их все как один фильтр.
Тогда фильтр будет выглядеть примерно так:
class BlogFilter(django_filters.FilterSet):
entry__headline = django_filters.CharFilter(grouped=True)
entry__pub_date = django_filters.CharFilter(grouped=True)
class Meta:
model = Blog
fields = ['entry__headline', 'entry__pub_date', ]