Djangoクエリセットフィルタリングで等しくない方法を教えてください。


666

DjangoモデルのQuerySetsには、__gt__ltの比較値がありますが、__ne/ !=/ <>等しくない?)

等しくないを使用してフィルタリングしたい:

例:

Model:
    bool a;
    int x;

が欲しいです

results = Model.objects.exclude(a=true, x!=5)

これ!=は正しい構文ではありません。私が試しました__ne<>

私は結局使用しました:

results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)

75
結果= Model.objects.exclude(a = true).filter(x = 5)は機能しましたか?
hughdbrown 2009

3
@hughdbrown。いいえ。クエリはa=true最初にすべてを除外してx=5から、残りのフィルターを適用します。意図したクエリではa=true、およびを使用するクエリのみが必要でしたx!=5。違いは、すべてのものされていることa=trueとはx=5また除外されます。
Mitchell van Zuylen、2018

回答:


690

たぶんQオブジェクトがこの問題の助けになるかもしれません。私はそれらを使用したことがありませんが、通常のpython式と同じように無効にして組み合わせることができるようです。

更新:私は試してみましたが、かなりうまくいくようです:

>>> from myapp.models import Entry
>>> from django.db.models import Q

>>> Entry.objects.filter(~Q(id = 3))

[<Entry: Entry object>, <Entry: Entry object>, <Entry: Entry object>, ...]

16
@JCLeitão:より直感的な構文については、以下の@ d4ntの回答も参照してください。
Paul D. Waite 14

611

クエリにダブルネガティブがあるようです。xが5でないすべての行を除外します。つまり、xが5のすべての行を含めます。これでうまくいくと思います。

results = Model.objects.filter(x=5).exclude(a=true)

特定の質問に答えるには、「等しくない」はありませんが、おそらくdjangoには「filter」と「exclude」の両方のメソッドが利用できるため、常にロジックを切り替えて目的の結果を得ることができます。


2
@ d4nt:私は間違っているかもしれませんが、クエリは正しいと思いますresults = Model.objects.filter(a=true).exclude(x=5)
Taranjeet

1
@Taranjeet:元のクエリを間違って読んだと思います。OPが除外(a = True)し、x = 5の除外を無効にする(つまり、含める)ため、d4ntのバージョンは正しいです。
チャック

3
インスタンス(x = 4、a = false)が誤って除外されるため、これは間違っていると思います。
RemcoGerlich 2015年

4
@danigosaそれは正しくないようです。私はこれを自分で試してみましたがexcludefilter呼び出しと呼び出しの順序には意味のある違いはありませんでした。WHERE条項の条件の順序は変更されますが、それはどのように重要ですか?
coredumperror

4
@danigosaの除外とフィルターの順序は関係ありません。
EralpB 2017

132

field=valueクエリの構文はの省略形ですfield__exact=value。つまり、Djangoは識別子のクエリフィールドにクエリ演算子を配置します。Djangoは以下の演算子をサポートしています:

exact
iexact
contains
icontains
in
gt
gte
lt
lte
startswith
istartswith
endswith
iendswith
range
year
month
day
week_day
isnull
search
regex
iregex

私のようにQオブジェクトとこれらを組み合わせることにより、確信しているデイブ・フォークトは示唆して使用しfilter()たりexclude()ジェイソン・ベイカーが示唆あなたはちょうど約すべての可能なクエリのために必要なものを正確に取得します。


おかげでこれは素晴らしいです。私はこのようなものを使用しtg=Tag.objects.filter(user=request.user).exclude(name__regex=r'^(public|url)$')、それは動作します。
suhailvs 2013

@suhail、すべてのデータベースがその正規表現構文をサポートしているわけではないことに注意してください:)
Anoyz

2
Iでicontainsiexactそして「大文字小文字の区別を無視する」ための同様のスタンド。「逆」ではありません。
Ivy Growing

exclude()複数の用語を使用している場合OR、たとえばexclude(Q(field1__queryop1=value1) | Q(field2__queryop2=value2))両方の条件での結果を除外するために、演算子を使用して命題を作成したい場合があることに注意してください。
clapas 2017

98

Django 1.7でカスタム検索を作成するのは簡単です。Djangoの公式ドキュメントに__neルックアップの例があります

最初にルックアップ自体を作成する必要があります。

from django.db.models import Lookup

class NotEqual(Lookup):
    lookup_name = 'ne'

    def as_sql(self, qn, connection):
        lhs, lhs_params = self.process_lhs(qn, connection)
        rhs, rhs_params = self.process_rhs(qn, connection)
        params = lhs_params + rhs_params
        return '%s <> %s' % (lhs, rhs), params

次に、それを登録する必要があります。

from django.db.models.fields import Field
Field.register_lookup(NotEqual)

そして今、あなたは__neこのようにあなたのクエリでルックアップを使うことができます:

results = Model.objects.exclude(a=True, x__ne=5)

88

ではジャンゴ1.9 / 1.10の3つのオプションがあります。

  1. チェーンexcludefilter

    results = Model.objects.exclude(a=true).filter(x=5)
  2. Q()オブジェクト演算子を使用する~

    from django.db.models import Q
    object_list = QuerySet.filter(~Q(a=True), x=5)
  3. カスタム検索関数を登録する

    from django.db.models import Lookup
    from django.db.models.fields import Field
    
    @Field.register_lookup
    class NotEqual(Lookup):
        lookup_name = 'ne'
    
        def as_sql(self, compiler, connection):
            lhs, lhs_params = self.process_lhs(compiler, connection)
            rhs, rhs_params = self.process_rhs(compiler, connection)
            params = lhs_params + rhs_params
            return '%s <> %s' % (lhs, rhs), params

    register_lookupデコレータは、で追加されましたDjangoの1.8といつものようにカスタム検索を可能にします:

    results = Model.objects.exclude(a=True, x__ne=5)

1
OBJECT_LIST = QuerySet.filter(〜Q(= TRUE)、X = 5):含有するものQ.後にQを含有していない他のすべての条件を維持することを忘れないでください
Bhumiシングハル

1
@MichaelHoffmann:A)〜Qを使用して除外した後、より少ないデータセットでフィルタリングするため、より効率的です。B)おそらく、逆の順序でのシーケンスは機能しません。
Bhumi Singhal

41

モデルで、あなたがしてフィルタリングすることもできますが=__gt__gte__lt__lte、あなたが使用することはできませんne!=または<>。ただし、Qオブジェクトを使用すると、より適切なフィルタリングを実現できます。

QuerySet.filter()との連鎖を回避してQuerySet.exlude()、これを使用できます。

from django.db.models import Q
object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')

24

保留中のデザイン決定。その間、exclude()

Djangoの課題トラッカーには、「クエリセットに「等しくない」フィルター演算子がありません」というタイトルの素晴らしいエントリー#5763 があります。(2016年4月現在)「Django石器時代」に「9年前に開店」、「4年前に閉店」、「5か月前に最後に変更された」ため、注目に値します。

ディスカッションを読んで、それは興味深いです。基本的に、何人かの人々は__ne追加されるべきであると主張する一方で、他の人々exclude()はより明確であるので追加される__ne べきではないと主張します。

(私は前者に同意します。後者の議論は、Pythonが持って!=いるはずであり==notすでに持っているからです...)



18

あなたは使用する必要がありますfilterし、excludeこれが好き

results = Model.objects.exclude(a=true).filter(x=5)

8

コードの最後のビットは、x!= 5でaがTrueであるすべてのオブジェクトを除外します。これを試して:

results = Model.objects.filter(a=False, x=5)

上記の行の=記号は、パラメーターaにFalseを割り当て、パラメーターxに数値5を割り当てていることに注意してください。等価性のチェックではありません。したがって、クエリ呼び出しで!=記号を使用する方法は実際にはありません。


3
これらのフィールドにはNull値も存在する可能性があるため、これは100%同じではありません。
MikeN 2009

これは、a = False および x = 5のアイテムのみを返しますが、質問にはインスタンス(a = false、x = 4)が含まれます。
RemcoGerlich 2015年

1
results = Model.objects.filter(a__in=[False,None],x=5)
ジェレミー

8

結果= Model.objects.filter(a = True).exclude(x = 5)
このSQLをGeneretes:
*をtablexから選択します。ここで、!= 0およびx!= 5です。
SQLは、True / Falseフィールドの表現方法とデータベースエンジンによって異なります。djangoのコードで十分です。



6

あなたが探しているのは、a=false または を持っているすべてのオブジェクトですx=5。Djangoでは、クエリセット間の演算子|として機能しますOR

results = Model.objects.filter(a=false)|Model.objects.filter(x=5)

5

これにより、希望する結果が得られます。

from django.db.models import Q
results = Model.objects.exclude(Q(a=True) & ~Q(x=5))

以下のために一致しないあなたが使用することができます~同じクエリに。明らかQに、同等のクエリに到達するために使用できます。


編集内容を確認してください。で「and」を使用Q(a=True) and ~Q(x=5)すると~Q(x=5)、の引数として評価されます.excludedocs.python.org/3/reference/expressions.html#boolean-operationsおよびdocs.python.org/3/reference/…をお読みください。
tzot

2

この質問に対する多くの不正解に注意してください!

Gerardのロジックは正しいですが、クエリセットではなくリストを返します(問題ではない可能性があります)。

クエリセットが必要な場合は、Qを使用します。

from django.db.models import Q
results = Model.objects.filter(Q(a=false) | Q(x=5))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.