python - 使用 Q 对象过滤多个外键匹配

标签 python django django-orm django-1.3 django-q

我已在 Django 1.3 下名为 main 的应用程序中使用以下数据初始化了这些模型:

from django.db.models import Model, FloatField, CharField, ForeignKey, Q

class Customer(Model):
    name = CharField(max_length=64)

class Order(Model):
    customer = ForeignKey(Customer)
    order_total = FloatField()
c = Customer(name="John Smith")
c.save()

Order(customer=c, order_id=9).save()
Order(customer=c, order_id=13).save()

如何使用 Q() 对象构建查询来查找拥有订单 9 和订单 13 的客户?

在不使用Q()对象的情况下,我可以使用.filter()方法两次来获得我想要的结果。正如您所看到的,它使用两个 JOIN 来查找两个外键:

queryset = Customer.objects.filter(order__order_id=9).filter(order__order_id=13)

return HttpResponse("%s\n\n%s" % (queryset, queryset.query), content_type="text/plain")
[<Customer: Customer object>]

SELECT "main_customer"."id", "main_customer"."name"
FROM "main_customer"
INNER JOIN "main_order" ON ("main_customer"."id" = "main_order"."customer_id")
INNER JOIN "main_order" T3 ON ("main_customer"."id" = T3."customer_id")
WHERE ("main_order"."order_id" = 9  AND T3."order_id" = 13 )

我尝试使用 Q() 对象执行相同的操作,如下所示。它并没有理解我指的是两个不同的订单,一个 id 为 9,一个 id 为 13,而是认为我正在寻找 id 为 9 和 13 的单个订单。这显然是不可能的,因此它不会返回任何结果:

q = Q(order__order_id=9) & Q(order__order_id=13)
queryset = Customer.objects.filter(q)

return HttpResponse("%s\n\n%s" % (queryset, queryset.query), content_type="text/plain")
[]

SELECT "main_customer"."id", "main_customer"."name"
FROM "main_customer"
INNER JOIN "main_order" ON ("main_customer"."id" = "main_order"."customer_id")
WHERE ("main_order"."order_id" = 9  AND "main_order"."order_id" = 13 )

我希望 Django 的引擎能够同等地解释这两个查询,但显然 Q() 对象的处理方式不同。如何使用 Q() 对象通过多个外键引用过滤对象,而不是多次调用 .filter()

最佳答案

我想我找到了解决这种情况的方法:

使用 filter( ~(~Q(A) | ~Q(B)) ) 而不是 filter(Q(A) & Q(B)) 似乎达到预期的结果。

这是基于 A 和 B 等同于 not ( not(A) or not(B) ) 的事实,并且可以对多个 进行过滤仅使用 Q 对象的foreignKey(最终传递给单个过滤器)。它相当丑陋,但最终仍然只使用一个数据库查询。

正如上面指出的,最初的问题来自于 .filter(A).filter(B)filter(A & B) 的不同行为(参见the doc 中的示例),并且 filter(Q(A) & Q(B)) 仅复制其中一种用途。

在我的例子中,生成的 SQL 查询太复杂,无法确保此解决方法完美工作,但我认为我应该分享这个想法,因为我的测试证明它有效。如果您确实证明/打破了它,请告诉我。

关于python - 使用 Q 对象过滤多个外键匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12462341/

相关文章:

Python 绘制时间序列并强调其中的一部分

django - pytest 和 Django 事务数据库

python - 单个django查询集获取n个相邻项目

python - Django ORM获取各自的选择值而不是字段值

python - 如何在python中动态创建属性?

python - map 100%减少100%,任务失败

mysql - 在 cygwin 中安装 mysql-python - 找不到 mysql_config [Windows 7]

python - Django 测试,断言 CSV 内容存在

django - 使用日期时间对象来过滤 Django 中的查询集(截断为天)

python - Cookie 未在 starlette TestClient 上设置,请求通过 Python 请求发送