gpt4 book ai didi

sql - 在 Django 中构造 Q 对象时保持 SQL 运算符优先级

转载 作者:行者123 更新时间:2023-12-03 01:03:26 26 4
gpt4 key购买 nike

我试图通过根据用户输入列表添加 Q 对象来在 Django 中构造一个复杂的查询:

from django.db.models import Q

q = Q()

expressions = [
{'operator': 'or', 'field': 'f1', 'value': 1},
{'operator': 'or', 'field': 'f2', 'value': 2},
{'operator': 'and', 'field': 'f3', 'value': 3},
{'operator': 'or', 'field': 'f4', 'value': 4},
]

for item in expressions:
if item['operator'] == 'and':
q.add(Q(**{item['field']:item['value']}), Q.AND )

elif item['operator'] == 'or':
q.add(Q(**{item['field']:item['value']}), Q.OR )

基于此,我期望得到具有以下条件的查询:

f1 = 1 or f2 = 2 and f3 = 3 or f4 = 4

根据默认运算符优先级,将执行为

f1 = 1 or (f2 = 2 and f3 = 3) or f4 = 4

但是,我收到以下查询:

((f1 = 1 or f2 = 2) and f3 = 3) or f4 = 4

看起来 Q() 对象强制条件按照添加的顺序进行评估。

有没有办法可以保持默认的 SQL 优先级?基本上我想告诉 ORM 不要在我的条件中添加括号。

最佳答案

似乎 you are not the only one with a similar problem .(根据 @hynekcer 的评论进行编辑)

解决方法是将传入参数“解析”为 Q() 对象列表,并从该列表创建查询:

from operator import or_
from django.db.models import Q

query_list = []

for item in expressions:
if item['operator'] == 'and' and query_list:
# query_list must have at least one item for this to work
query_list[-1] = query_list[-1] & Q(**{item['field']:item['value']})
elif item['operator'] == 'or':
query_list.append(Q(**{item['field']:item['value']}))
else:
# If you find yourself here, something went wrong...

现在,query_list 包含各个查询,如 Q() 或它们之间的 Q() AND Q() 关系。
该列表可以使用 or_ 运算符进行 reduce() 处理,以创建剩余的 OR 关系并在 filter()< 中使用get() 等查询:

MyModel.objects.filter(reduce(or_, query_list))
<小时/>

PS:虽然Kevin's answer很聪明,using eval() is considered a bad practice应避免。

关于sql - 在 Django 中构造 Q 对象时保持 SQL 运算符优先级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45194767/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com