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

标签 sql django orm

我试图通过根据用户输入列表添加 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/

相关文章:

mysql - SQL 数据库中的非规范化或规范化(继承数据)

sql - MySQL在html文本字段中搜索文本?

sql - 计数、排序并选择前 5 个

Django - Timeuntil标签输出缩写

python - Django 1.9a1 __init__.py 在 eclipse/PyDev 中可见,即使它应该被删除 (Windows)

database - DBIinit DatabaseTablesPreparer NullPointerException

mysql - 如何扩展 Doctrine 2 以处理 CodeIgniter 2 中的 MySQL 空间 ("point"字段类型)?

sql - 动态SQL语法错误SQLScript SAP HANA

java - 有没有办法在 Java App Engine 中重用 MySQL Db 连接

python - Django 错误 "add a non-nullable field"