获取与Django查询集相关的模型
我对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 *
而不是指定字段,我就能在一次查询中得到我需要的所有数据。有没有办法构建这样的查询,只获取与之相关的数据呢?
编辑
我觉得我需要澄清一些点,抱歉之前没有说得更清楚:
我不在
OrderProduct
上查询,因为有些产品是公开的,不需要购买,但我仍然需要列出它们,这些产品不会通过对OrderProduct
的查询返回。我期待的结果是一个产品列表,以及它们的订单数据(如果有的话)。在JSON格式中,大概是这样的:
[{id: 1, order: 1, expiration: 2013-03-03, public: false}, {id: 1, order: , expiration: , public: true
谢谢
2 个回答
我本来想推荐一个叫 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
我想获取所有与Product1相关的OrderProduct,但我只想要从我的查询集中返回的那一个。
你想要的是哪一个“一个”?你的查询是针对Product
模型进行筛选的,所以与返回的查询集中每个Product
相关的所有Users
、Orders
和OrderProducts
都可以访问。
如果你想要一个特定的OrderProduct
,那么你应该这样筛选:op = OrderProduct.objects.filter(xxxxx)
,然后像这样访问上层的模型:op.product
、op.order
,等等。