首页 > 解决方案 > Django 查询:返回一个将转换为“AND (...)”的 Q 对象

问题描述

我正在为我们的网站编写一个简单的搜索,我需要根据一些条件过滤条目。但是,如果不满足最严格的过滤,我想返回结果以进行不太严格的搜索。为此,我想创建许多查询对象,每个查询对象都有一个过滤器,然后向后迭代它们以获取结果,并返回我以这种方式得到的第一个。

我正在做的是:

q0 = MyIndex.objects.in_city(city_id)
q1 = q0.filter(name_contains(words))

在哪里

def name_contains(words):
    if not words:
        return Q()
    query = Q(words_contains=words[0])
    for word in word[1:]:
        query = query | Q(words_contains=word)

当我传递数据库中不存在的单词时,我仍然得到一个结果,因为返回的查询部分是通过而不是name_contains附加的。ORAND

有没有办法可以返回该查询,以便它始终附加到查询的其余部分AND

标签: djangodjango-modelsdjango-ormdjango-q

解决方案


除非你有一个奇怪的对象管理器,否则in_city可能会换成.filter(..).

如果您链接多个.filter(..)s,那么您在两者之间隐式编写了一个逻辑,因为您的第一个filter(..)实际上已经删除了不满足要求的元素,而您的第二个过滤器只过滤了更多。

您可以通过打印 Django 将执行的底层查询来验证这种怀疑:

print(str(q0.filter(name_contains(words)).query))

请注意,您可以使您的函数更具声明性,例如:

from functools import reduce
from operator import or_

def name_contains(words):
    if words:
        return reduce(or_, (Q(word_contains=word) for word in words))
    else:
        return Q()

推荐阅读