web-dev-qa-db-ja.com

Djangoフィルタと除外

Djangoでfilterとexcludeに違いはありますか?私が持っている場合

self.get_query_set().filter(modelField=x)

さらに別の基準を追加したいのですが、次の2行のコードとの間に意味のある違いはありますか?

self.get_query_set().filter(user__isnull=False, modelField=x)

self.get_query_set().filter(modelField=x).exclude(user__isnull=True)

1つはより良い実践と考えられていますか、それとも機能とパフォーマンスの両方で同じですか?

31
Enrico

どちらも遅延評価されるため、同等のパフォーマンスが期待されます。 SQLはおそらく異なりますが、実際の違いはありません。

22
Ned Batchelder

一般的に、除外はフィルターの反対です。この場合、両方の例は同じように機能します。

ここに:

self.get_query_set().filter(user__isnull=False, modelField=x)

フィールドuserがnullではなく、modelFieldの値がxであるエントリを選択します

この場合:

self.get_query_set().filter(modelField=x).exclude(user__isnull=True)

最初に、modelFieldの値がx(userがnullで、userがnullではない)のエントリを選択してから、userフィールドがnullのエントリを除外します。

この場合、最初のオプションを使用する方が良いと思います。しかし、どちらも同じように機能します。

19
Dominik Szopa

何を達成したいかによります。ブール値を使用すると、 .exclude().filter() を簡単に切り替えることができますが、たとえば3月の記事以外のすべての記事を取得したい場合は、クエリは次のように書くことができます

_Posts.objects.exclude(date__month=3)
_

.filter()を使用すると、次のようになります(ただし、これが実際に機能するかどうかはわかりません)。

_Posts.objects.filter(date__month__in=[1,2,4,5,6,7,8,9,10,11,12])
_

または Q オブジェクトを使用する必要があります。

関数名がすでに示唆しているように、.exclude()を使用して、結果セットからデータセットをexclude除外します。ブール値の場合、これを簡単に反転して.filter()を代わりに使用できますが、他の値の場合、これはよりトリッキーになる可能性があります。

13
Felix Kling