我正在使用django-filter应用。但是有一个问题我不知道如何解决。它与django文档中描述的几乎完全相同:
https://docs.djangoproject.com/en/1.2/topics/db/queries/#spanning-multi-valued-relationships
我想进行一个查询,我选择所有博客的标题为 “Lennon”的标题和于2008年发布,例如:
Blog.objects.filter(entry__headline__contains='Lennon',
entry__pub_date__year=2008)
不选择标题中包含“Lennon”条目和2008年发布的另一条目(可能相同)的博客:
Blog.objects.filter(entry__headline__contains='Lennon').filter(
entry__pub_date__year=2008)
但是,如果我设置Filter,那么有两个字段(nevermind __contains x __exact,只是一个例子):
class BlogFilter(django_filters.FilterSet):
entry__headline = django_filters.CharFilter()
entry__pub_date = django_filters.CharFilter()
class Meta:
model = Blog
fields = ['entry__headline', 'entry__pub_date', ]
django-filter将生成后者:
Blog.objects.filter(entry__headline__exact='Lennon').filter(
entry__pub_date__exact=2008)
有没有办法将两个过滤器组合成一个过滤器字段?
答案 0 :(得分:1)
好吧,我带来了一个解决方案。使用常规的django-filter是不可能的,所以我稍微扩展了一下。可以改进,这是一个快速解决方案。
1st向django_filters.Filter和filter_grouped方法添加了一个自定义的“分组”字段(几乎是过滤方法的副本)
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 {}
唯一的区别是,它不是在查询集上创建过滤器,而是返回字典。
第二次更新的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', ]