2012-09-29 7 views
11

フィルタのセットを使用してデータベースから一連の行を取得したいとします。djangoは条件付きでオブジェクトをフィルタリングします

条件付きフィルタがdjangoに適用できるかどうか疑問に思っていました。つまり、「変数がNoneでない場合にフィルタリングするか、そうでなければフィルタリングを適用しない」です。このような

何か:私は何をしたいのカテゴリがNoneでない場合にのみ、カテゴリフィルタを適用している

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)) 

カテゴリがNone(要求オブジェクトに指定されていないことを意味します)の場合、このフィルタはまったく適用されません。これは私に「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)) 

で再生することです。

category__isnull == True

編集によるOPのコメントはデータベースに、アイテムが関連するカテゴリをしていない、ということを意味します。 はおそらく、あなたが探しているクエリは次のとおりです。

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を理解していません。この状況に当てはまりますか?「カテゴリ」を含むフォーム。ユーザーがフォームを入力して送信します。ユーザーが「カテゴリ」を入力しないと、この値は「カテゴリ」になります。あなたの1番目の例に従えば、 "category"という制約なしにデータベースをフィルタリングしますか?私の理解が正しいなら、私を修正してください。前もって感謝します。 –

4

まあ、これはかなり古い質問ですが、1つの行に条件付きのフィルタリングを行うたい人のために、ここで(ところで、次のコードは、おそらくより一般的な方法で書き込むことができます)私のアプローチです:

あなたが見る必要があるのは、user=userのようなキーワード引数の前にconditional_category_filter(category)コールを使用することだけです。たとえば、次のコードはエラーをスローします:

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