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字段类型
将 django ValuesQuerySet 转换为 json 对象