【问题标题】:Django filter multiple columns with a list of tuplesDjango 使用元组列表过滤多个列
【发布时间】:2025-12-07 18:10:01
【问题描述】:

我有一个包含 2 个字段的简单模型:

class Simple(Model)
    class Meta:
        index_together = True

    a = IntField()
    b = IntField()

我想为 a,b 的值元组生成 SQL 查询。 例如

select * 
from SimpleModel 
where (a,b) in ((1,1), (4,8), ...)

我知道如何创建类似的东西:

select * 
from SimpleModel 
where ((a = 1 and b = 1) or (a = 4 and b = 8))

这在逻辑上是相同的,但我认为我的数据库在可能值的数量非常大时会出现问题(我使用的是 Postgresql),而且查询本身要长得多,因此它在网络上更重,而且可能更难以便它能够正确分析和读取它(即在这种情况下使用复合索引)。

那么,问题是,我可以让 Django 以第一种形式创建查询吗?

谢谢!

【问题讨论】:

    标签: sql django-models


    【解决方案1】:

    是的,但只能*使用extrawhere 参数:https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.extra

    应该这样做:

    Simple.objects.extra(where=['(a,b) in %s' % your_list])
    

    *如果您创建自定义数据库类型,您应该能够定义自定义运算符,所以...也许能够解决它。我会谷歌一下:)

    【讨论】:

    • 请注意,从 Django 1.8 开始,对 .extra 的支持将被逐步淘汰
    • @MrDBA:它不会在不久的将来被淘汰,因为当前的开发仍然支持它。就我个人而言,我强烈认为他们应该重新考虑删除的决定,因为总会有一些情况下支持较低级别的自定义查询是有用的。
    【解决方案2】:

    @Wolph 的答案是正确的,但我会这样做

    tuple_of_tuples = ((1,1), (4,8))
    Simple.objects.extra(where=['(a,b) in %s'], params=[tuple_of_tuples])
    

    在此处查看有关传递元组而不是列表的信息

    Passing lists or tuples as arguments in django raw sql

    对于params,我引用了 Django 文档 https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.extra

    参数

    上面描述的where参数可以使用标准的Python数据库 字符串占位符 — '%s' 表示数据库引擎的参数 应该自动报价。 params 参数是任何额外的列表 要替换的参数。

    例子:

    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])

    始终使用 params 而不是将值直接嵌入到 where 中,因为 params 将确保根据您的正确引用值 特定的后端。例如,引号将被正确转义。

    【讨论】:

      最近更新 更多