2012-09-29 91 views
11

我想使用一組過濾器從我的數據庫中檢索一堆行。django有條件地過濾對象

我想知道如果條件過濾器是適用於django。也就是說,「如果變量不是無,或者不應用其他過濾」。

事情是這樣的:

user = User.objects.get(pk=1) 
category = Category.objects.get(pk=1) 
todays_items = Item.objects.filter(user=user, date=now()).conditional_filter(category=category)) 

我想要做的是應用類別過濾器,只有當類別不是無。

如果類別是無(表示它沒有在請求對象中給出),那麼這個過濾器根本就不會被應用。這會爲我節省一堆「if-elif-else」情況。

有沒有辦法做到這一點?

回答

15

您可以查詢鏈:

user = User.objects.get(pk=1) 
category = Category.objects.get(pk=1) 
qs = Item.objects.filter(user=user, date=now()) 
if category: 
    qs = qs.filter(category=category) 

由於查詢集懶洋洋地執行,當你擺放物品時纔會發生DB命中。

2

他們是你的問題的幾種方法。一種方法是用Complex lookups with Q objects

from django.db.models import Q 

user = User.objects.get(pk=1) 
category = Category.objects.get(pk=1) 

f1 = Q(user=user, date=now()) 
f_cat_is_none = Q(category__isnull = True) 
f_cat_is_not_none = Q(category=category) 

todays_items = Item.objects.filter(f1 & (f_cat_is_none | f_cat_is_not_none)) 

玩,我不就在你的答案明白,如果這是你正在尋找的查詢,但是,這個例子中,你可以很容易地編寫自己的查詢。

編輯由於OP評論

category__isnull == True意味着,在數據庫中,該項目還沒有相關的類別。 也許你正在尋找的查詢是:

from django.db.models import Q 

user_pk = 1 
category_pk = 1 #some times None 

f = Q(user__pk = user_pk, date=now()) 
if category_pk is not None: 
    f &= Q(category__pk = category_pk) 

todays_items = Item.objects.filter(f ) 

這僅僅是一個代碼示例,它符合您的要求。注意單個_和雙重__

+0

謝謝,我不明白的是'category__isnull = True'。我的對象都沒有在其分類字段中有NULL。這使得它永遠是假的。 – xpanta

+0

@xpanta,解答回答。 – danihp

+0

@danihp,對不起,我還是不太明白__isnull = True。它是否適用於這種情況:包含「類別」的表單,用戶填寫並提交表單。如果用戶沒有輸入「類別」,則此值爲「」。然後過濾數據庫沒有「類別」的約束,如果我跟着你的第一個例子?如果我的理解正確,請糾正我。提前致謝。 –

4

好了,這是相當老的問題,但對於那些誰願意做一個線條件過濾,這裏是我的做法(順便說一下,下面的代碼可能可以在一個更通用的方法寫的):

from django.db.models import Q 

def conditional_category_filter(category): 
    if category != None: 
     return Q(category=category) 
    else: 
     return Q() #Dummy filter 

user = User.objects.get(pk=1) 
category = Category.objects.get(pk=1) 
todays_items = Item.objects.filter(conditional_category_filter(category), user=user, date=now()) 

你需要注意的唯一的事情就像是user=user關鍵字參數之前使用conditional_category_filter(category)通話。例如下面的代碼會拋出一個錯誤:

todays_items = Item.objects.filter(user=user, date=now(), conditional_category_filter(category))