web-dev-qa-db-ja.com

Django in / not query

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というモデルを仮定するとどのようになりますか?

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

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

148
Harph

これらのモデルでは:

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)
10
table1.objects.extra(where=["table1.id NOT IN (SELECT table2.key_to_table1 FROM table2 WHERE table2.id = some_parm)"])
5
ibz

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

From documentation「簡単なカスタムルックアップから始めましょう。カスタムルックアップを書きますneこれはexactと反対に機能しますAuthor.objects。 filter(name__ne = 'Jack')は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
1
Blairg23