Django in / not query


100

私はdjangoで「not in」スタイルのクエリを作成する方法を理解しようとしています。たとえば、私が考えているクエリ構造は次のようになります。

select table1.* 
from table1
where table1.id not in 
(
  select table2.key_to_table1
  from table2 
  where table2.id = some_parm 
)

djangoの構文は、table1とtable2と呼ばれるモデルを想定してどのように見えますか?

回答:


163
table1.objects.exclude(id__in=
    table2.objects.filter(your_condition).values_list('id', flat=True))

exclude関数Notは、求めている演算子のように機能します。属性flat = Trueは、1レベルのリストとしてtable2を返すようにクエリに指示しますvalue_list。つまり...最後にIDs、table2からリストを取得します。これを使用して、条件を定義しtable1ます。これは、exclude関数によって拒否されます。


3
リストコンストラクター[table2 ...]-> list(table2 ...)でも問題がありました。
RickyA

3
修正:table1.objects.exclude(id__in = table2.objects.filter(your_condition).values_list( 'id'、flat = True))
Richard

1
このソリューションを使用しようとして問題が発生したため、他の誰かに起こった場合... Objs=Tbl1.objects.filter(...); IDs=Objs.values_list('id', flat=True); Objs.delete(); Tbl2.objects.filter(id__in=IDs')IDは実際にはQuerySetオブジェクトであるため、これは機能しませんでした。元の行を削除すると、他のクエリでは機能しなくなりました。解決策はTbl2.objects.filter(id__in=list(IDs))、それをリストに変換することです
Dakusan '

1
コンテキストに応じて、「annotate()habing count(xx)== yy」のようなフィルターの場合、100倍以上高速に使用できます(timeitにより1.0497902309998608対0.00514069400014705が返されます)
Olivier Pons

10

これらのモデルで:

class table1(models.Model):
    field1 = models.CharField(max_length=10)      # a dummy field

class table2(models.Model):
    key_to_table1 = models.ForeignKey(table1)

あなたはあなたが使いたいものを得るはずです:

table1.objects.exclude(table2=some_param)

1
これでも、潜在的に大量のレコードをデータベースから不必要にプルする可能性があります。
Jay Taylor

5
table1.objects.extra(where=["table1.id NOT IN (SELECT table2.key_to_table1 FROM table2 WHERE table2.id = some_parm)"])

1

Djangoクエリのカスタムルックアップを作成できます。

ドキュメント 「単純なカスタム検索を行ってみましょうスタート我々は、カスタム検索書きますねっし、反対に動作します正確なのAuthor.objects.filter(name__ne = 『ジャック』) SQLに変換します。"author"."name" <> 'Jack'

from django.db.models import 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

-16
[o1 for o1 in table1.objects.all() if o1.id not in [o2.id for o2 in table2.objects.filter(id=some_parm)]]

以上

not_in_ids = [obj.id for obj in table2.objects.filter(id=some_parm)]
selected_objects = [obj for obj in table1.objects.iterator() if obj.id not in not_in_ids]

12
テーブルのすべての行を反復します。gg
2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.