簡體   English   中英

如何按記錄列表過濾 __in django ORM?

[英]How can I filter __in django ORM by records list?

我希望這樣的查詢:

SELECT field1, field2, field3
FROM mytable
WHERE (field1, field2) NOT IN(
    (1, 1), 
    (2, 2)
);

django==1.9.13

我目前的解決方案是:

qs = MyTable.objects.all()
for (field1, field2) in data:  # List[Tuple[int, int]]
    qs = qs.exclude(field1=field1, field2=field2)

如果您真的需要,您可以使用 ORM 實現幾乎精確的 SQL 查詢。

from django.db.models import Func, Field, Lookup    

class Tuple(Func):
    function = ''
    template = '(%(expressions)s)'

@Field.register_lookup
class NotIn(Lookup):
    lookup_name = 'not_in'

    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 NOT IN %s' % (lhs, rhs), params

qs = (MyTable.objects.annotate(tup_fields=Tuple('field1', 'field2', output_field=Field()))
             .filter(tup_fields__not_in=data))

這將產生 SQL 之類的

SELECT field1, field2, field3, (field1, field2) as tup_fields
FROM mytable
WHERE ((mytable.field1, mytable.field2) NOT IN ((1, 1), (2, 2)));

您可以不使用NotIn(Lookup) class 並執行.filter(~Q(tup_fields__in=data)) 這將生成一個類似於NOT (field1, field2) IN (...)的 where 子句。

您也可以按照自己的方式進行操作,這可能很好。 生成的SQL不同,但結果是一樣的。 我不確定是否存在對您很重要的性能差異。

在這里你可以這樣做

from django.db.models import Q

query = Q()

for (field1, field2) in data:  # List[Tuple[int, int]]
    query.add(Q(field1=field1, field2=field2), Q.OR)

qs = MyTable.objects.exclude(query)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM