2011-11-12 80 views
2

我正在使用django-filter應用程序。然而,有一個問題我不知道如何解決。這幾乎完全一樣Django文檔中描述了同樣的事情:將幾個過濾器組合成一個過濾器()與Django過濾器

https://docs.djangoproject.com/en/1.2/topics/db/queries/#spanning-multi-valued-relationships

我想打一個查詢,我選擇在標題「儂」的條目的所有博客是在2008年出版,如:

Blog.objects.filter(entry__headline__contains='Lennon', 
    entry__pub_date__year=2008) 

,不要選擇在標題爲「列儂」的條目並於2008年出版的另一入口(可能是相同的)博客:

Blog.objects.filter(entry__headline__contains='Lennon').filter(
    entry__pub_date__year=2008) 

然而,如果我設置過濾器,使得有兩個字段(沒關係__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的過濾器將generete後者:

Blog.objects.filter(entry__headline__exact='Lennon').filter(
    entry__pub_date__exact=2008) 

有沒有辦法將兩個過濾器合併到一個過濾器字段中?

+0

對不起,復活這種老線,但 'Foo.objects.filter(FOO = 「酒吧」)過濾器(qux = 「QUUX」) ' 實際上與 相同'Foo.objects.filter(foo =「bar」,qux =「quux」)' 多個關鍵字參數和隨之而來的過濾器被「AND」編輯在一起。要創建「OR」過濾器,您必須使用'Q'對象:https://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q-objects – cvk

+0

@cvk hi ,根據https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships(包括dev和1.2版本)使用兩個鏈接過濾器產生「選擇所有包含在標題中加入「Lennon」的條目以及2008年發佈的條目「但使用帶有逗號的單一條款時,它會生成」選擇包含標題爲「Lennon」且2008年出版的條目的所有博客(滿足兩個條件的同一條目)「。這是一個巨大的差異。我還沒有找到使用django-filter的方法 –

回答

1

那麼,我來一個解決方案。使用常規的Django過濾器是不可能的,所以我擴展了一下。可能會有所改進,這是一個快速ñ骯髒的解決方案。

第一添加定製的「分組」字段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適量方法/屬性:

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', ]