获取与Django查询集相关的模型

1 投票
2 回答
2500 浏览
提问于 2025-04-17 17:36

我对Django的经验不多(我用的是1.3版本),所以我心里觉得这个问题可能有点傻……不过无论如何:

我有这样的模型:

class User(models.Model):
    name = models.CharField()

class Product(models.Model):
    name = models.CharField()
    public = models.BooleanField()

class Order(models.Model):
    user = models.ForeignKey(User)
    product = models.ManyToManyField(Product, through='OrderProduct')

class OrderProduct(models.Model):
    product = models.ForeignKey(Product)
    order = models.ForeignKey(Order)
    expiration = models.DateField()

假设我做了一个查询,像这样:

Product.objects.filter(order__status='completed', order__user____id=2)

这样我就能得到User2购买的所有产品(假设只有Product1)。不错。但现在我想知道这个产品的过期时间,如果我调用Product1.orderproduct_set.all(),我会得到所有与Product1相关的OrderProduct条目,但我只想要我查询结果中的那一条。我知道我可以在OrderProducts上再跑一个查询,但那样又要多一次数据库请求,来获取之前查询已经能得到的数据。对.query的调用给我返回:

SELECT "shop_product"."id", "shop_product"."name"
FROM "shop_product"
INNER JOIN "shop_orderproducts" ON ("shop_product"."id" = "shop_orderproducts"."product_id")
INNER JOIN "shop_order" ON ("shop_orderproducts"."order_id" = "shop_order"."id")
WHERE ("shop_order"."user_id" = 2  AND "shop_order"."status" = completed )
ORDER BY "shop_product"."ordering" ASC

如果我能用SELECT *而不是指定字段,我就能在一次查询中得到我需要的所有数据。有没有办法构建这样的查询,只获取与之相关的数据呢?

编辑

我觉得我需要澄清一些点,抱歉之前没有说得更清楚:

  1. 我不在OrderProduct上查询,因为有些产品是公开的,不需要购买,但我仍然需要列出它们,这些产品不会通过对OrderProduct的查询返回。

  2. 我期待的结果是一个产品列表,以及它们的订单数据(如果有的话)。在JSON格式中,大概是这样的:

    [{id: 1, order: 1, expiration: 2013-03-03, public: false}, {id: 1, order: , expiration: , public: true

谢谢

2 个回答

0

我本来想推荐一个叫 prefetch_related 的方法,但在 Django 1.3 版本中是用不了的。

Dan Hoerst 说得对,从 OrderProduct 中选择数据确实是对的,但这样还是会多次访问数据库,效率不高。我们可以通过使用 select_related 方法来避免这种情况。

>>> from django.db import connection
>>> len(connection.queries)
0
>>> first_result = OrderProduct.objects.select_related("order__user", "product")
...               .filter( order__status="completed",
...                        order__user__pk=2 )[0]
>>> len(connection.queries)
1
>>> name = first_result.order.user.name
>>> len(connection.queries)
1
>>> product_name = first_result.product.name
>>> len(connection.queries)
1
1

我想获取所有与Product1相关的OrderProduct,但我只想要从我的查询集中返回的那一个。

你想要的是哪一个“一个”?你的查询是针对Product模型进行筛选的,所以与返回的查询集中每个Product相关的所有UsersOrdersOrderProducts都可以访问。

如果你想要一个特定的OrderProduct,那么你应该这样筛选:op = OrderProduct.objects.filter(xxxxx),然后像这样访问上层的模型:op.productop.order,等等。

撰写回答