如何在Django过滤器中使用"AND"?

90
如何在Django中创建一个“AND”过滤器来检索对象?例如,我想要检索一个单个字段中包含两个词的行。
例如,当我在MySQL数据库上运行以下SQL查询时,它正好做到了这一点:
SELECT * FROM myapp_question
WHERE ((question LIKE '%software%') AND (question LIKE '%java%'))

如何在Django中使用过滤器来实现这个功能?
4个回答

169

为了深入了解,让我们提一下Q对象方法:

from django.db.models import Q
criterion1 = Q(question__contains="software")
criterion2 = Q(question__contains="java")
q = Question.objects.filter(criterion1 & criterion2)

请注意,这里的其他答案更简单,更适合您的用例,但如果有类似但稍微复杂一些的问题(例如需要“非”或“或”),看到这个问题时,就可以在此处找到参考。


6
只是想提一下,你那个不经意的评论对我有帮助。谢谢! - Alfonsol
更多信息请参见此处:https://docs.djangoproject.com/en/3.1/topics/db/queries/#complex-lookups-with-q - theQuestionMan

113

(更新:此答案将不再起作用并会出现语法错误keyword argument repeated)

mymodel.objects.filter(first_name__icontains="Foo", first_name__icontains="Bar")

更新:我写这篇答案已经有一段时间了并且做了一些 Django,但是直到今天我仍然相信最好的方法是使用 Q 对象方法,就像 David Berger 在这里展示的那样:如何在 Django 中使用 AND 过滤器?


5
这在Django 1.6和Postgres中对我无效。每当有两个或更多相同的关键字时,我会收到“SyntaxError: keyword argument repeated”错误。只有David Berger提出的使用Q的解决方案有效。 - margusholland
1
我有一个名为Country的模型,其中包含一个短国家代码字段(cc_short):
countries = Country.objects.filter(cc_short__icontains='A', cc_short__icontains='B') File "<console>", line 1 SyntaxError: 关键字参数重复
- margusholland
1
这对我也不起作用。和@margusholland一样的错误。使用Django 1.7.5。有问题的代码:talks = Talks.objects.filter(description__contains=topics,description__contains=terms).order_by('-datetime') topics和terms都是列表。 - Austin A
7
请注意,这两个字段是相同的!问题在于Python本身不允许这样做,在任何Django/DB中都行不通。这不应该被视为一个可接受的答案。 - rsalmei
1
嘿@MayankMehtani,如果关键字参数本身不同而不仅仅是它们的值,则应该可以工作。 - rsalmei
显示剩余6条评论

17
您可以在Django中链接过滤表达式:
q = Question.objects.filter(question__contains='software').filter(question__contains='java')

您可以在Django文档中找到更多信息,位于"链式筛选器"。


15
根据你的场景,这个答案可能会给你错误的结果。在过滤器中使用逗号和连接多个过滤器可能会产生不同的结果。更多阅读资料请参考:SO Answer官方文档 - user
1
OP想要的是allobjects.filter(name=x或name=y),但这个答案会先给出allobjects.filter(name=x),然后再过滤first.filter(name=y)。希望你们能理解。对于伪代码表示抱歉。 - mohammed_ayaz
3
题目要求进行“与”操作,而不是“或”操作。 - mipadi
我真的很好奇为什么这个答案会被点赞。除了这个具有OR逻辑之外,如果过滤字段来自引用表,它将会有不同的结果。 - Alex M.M.
1
@Alexandru-MihaiManolescu:什么是OR逻辑?这个问题是AND,不是OR。 - mipadi
1
OneToManyM2M 关系中,应该谨慎使用它,因为它适用于与主模型链接的任何对象,而不一定是由先前的 filter() 调用选择的那些对象。 - Amin Mir

3

您可以使用ANDfilter(),使用&Q()&,如下所示:

# "store/views.py"

from .models import Question
from django.db.models import Q
from django.http import HttpResponse

def test(request):

    # With "&"
                                                              # ↓ Here
    qs = Question.objects.filter(question__contains="software") & \ 
         Question.objects.filter(question__contains="java")
    print(qs)

    # With "Q()" and "&"
                               # ↓ Here                         # ↓ Here
    qs = Question.objects.filter(Q(question__contains="software") & 
                                 Q(question__contains="java"))
    print(qs)                  # ↑ Here

    return HttpResponse("Test")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接