Django Q过滤器,无法在单个查询中获得结果

Django Q filter, cant get results in a single query

我想使用多个条件进行查询以从我的订单模型中获取一些对象,但我找不到在单个查询中获取所有结果的方法。除了进行 2 个查询的选项外,我想知道这是否可以只用一个查询,这样我就可以创建一个包含所有这些订单的 CSV sheet(这部分已经有效,所以我将坚持查询)。 条件:

支付方式:Paypal 和 Mollie
created_at:以小时为单位 15:00 和 16:00

&

支付方式:ApplePay
created_at:以小时为单位 17:00 和 18:00

两个查询:

Order.objects.all() \
.filter(Q(paymethod="Paypal") | 
        Q(paymethod="Mollie") & 
        Q(created_at__hour__in=(15, 16)))


Order.objects.all() \
.filter(Q(paymethod="ApplePay") 
        Q(created_at__hour__in=(17, 18)))

这两个查询单独运行良好,但我想知道是否可以将它们合并为一个查询。

我试过类似的东西:

Order.objects.all() \
.filter(Q(paymethod="Paypal" | "Mollie", created_at__hour__in=(15, 16)) \
& Q(paymethod="ApplePay", created_at__hour__in=(17, 18)))

上述方法不起作用,因为:TypeError:不支持 | 的操作数类型:'str' 和 'str'。 所以我尝试了 paymethod="Paypal" | "Mollie" 而不是 paymethod="Paypal" | paymethod="Mollie" 但不幸的是,这也行不通..

如果有人能指出我正确的方向,我将不胜感激。我还在学习 django,django Q 对我来说是新的。如果需要任何其他信息,请告诉我!谢谢!

您可以使用嵌套的 Q 对象执行此操作,如下所示:

Order.objects.filter(
    Q(
        Q(paymethod="Paypal") | Q(paymethod="Mollie") & Q(created_at__hour__in=(15, 16))
    ) |
    Q(
        Q(paymethod="ApplePay") & Q(created_at__hour__in=(17, 18))
    )
)

您可以进一步嵌套子查询,如下所示:

Order.objects.filter(
    Q(
        Q(paymethod="Paypal") | 
        Q(paymethod="Mollie") & 
        Q(created_at__hour__in=(15, 16))
    ) |
    Q(
        Q(paymethod="ApplePay") 
        Q(created_at__hour__in=(17, 18))
    )
)

更新: 此外,如果您出于某种原因不想使用 'Q' 对象,您可以“合并”查询集:

q1 = Order.objects.all() \
.filter(Q(paymethod="Paypal") | 
        Q(paymethod="Mollie") & 
        Q(created_at__hour__in=(15, 16)))

q2 = Order.objects.all() \
.filter(Q(paymethod="ApplePay") 
        Q(created_at__hour__in=(17, 18)))

result = q1 | q2

我认为您根本不需要使用 Q。此用例应包含在 QuerySet.filterQueryset.union.

Order.objects.filter(
    paymethod__in=["Paypal", "Mollie"], 
    created_at__hour__in=[15, 16],
).union(
    Order.objects.filter(
        paymethod="ApplePay", 
        created_at__hour__in=[17, 18],
    )
)

当您将多个参数传递给 filter 时,django 将在生成的 sql 语句中使用 sql AND。这相当于用集合交集运算符 &.

加入你的 Q 对象

QuerySet.union 方法等同于查询集上的 | 运算符 并将转换为 sql UNION。 (Q 对象上的 | 运算符将转换为 sql OR 操作。)

接受 param__in=[...] 的 Django 查询集方法会将这些参数转换为 sql IN 语句。这应该等同于(给出相同的结果)使用 Q | Q.

filter(paymethod__in=["Paypal", "Mollie"])
# produces same results as 
filter(Q(paymethod="Paypal") | Q(paymethod="Mollie"))

我怀疑 IN 在典型情况下速度更快,但您可以通过基准测试来证实这一点。