Django 查询:返回一个将转换为“AND (...)”的 Q 对象

Posted

技术标签:

【中文标题】Django 查询:返回一个将转换为“AND (...)”的 Q 对象【英文标题】:Django queries: return a Q object that will translate to "AND (...)" 【发布时间】:2018-11-18 13:46:32 【问题描述】:

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

我正在做的是:

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 返回的查询部分是通过OR 而不是AND 附加的。

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

【问题讨论】:

| 替换为& @WillemVanOnsem 我需要此查询中的部分由“或”连接。也就是说,我需要查询以“... where city_id=3 and (words like "%one%" or words like "%two%)" 除非你的in_city 过滤器有一些非常奇怪的逻辑,否则它已经执行了这样的查询。您可以通过打印print(str(MyIndex.objects.in_city(city_id).filter(name_contains(words)).query)) 来调查此问题。 您可以将经理的代码与您的in_city 参考一起发布吗? 【参考方案1】:

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

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

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

print(str(q0.filter(name_contains(words))<b>.query</b>))

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

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()

【讨论】:

我需要用“或”连接这个查询中的部分。也就是说,我需要查询以“... where city_id=3 and (words like "%one%" or words like "%two%)" 在仔细检查我的代码后,我意识到,我没有传递一个 list 单词,而是传递了一个单词,并且字符串是可迭代的,该单词被拆分为字符,因此我得到了错误的结果。 @Ibolit:是的,字符串也是可迭代的字符。不幸的是,这经常导致错误:s.

以上是关于Django 查询:返回一个将转换为“AND (...)”的 Q 对象的主要内容,如果未能解决你的问题,请参考以下文章

将django RawQueryset中字段的值转换为不同的django字段类型

将 MySql 查询转换为 Django ORM 查询

将 django ValuesQuerySet 转换为 json 对象

Django / PostgresQL jsonb (JSONField) - 将选择和更新转换为一个查询

如何将此 SQL 查询转换为 Django?

将 SQLQuery 转换为 django 查询