我没有太多使用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()
,我将得到OrderProduct
的每一个包含Product1
的条目,但是我只想要从我的查询集中返回的那个。我知道我可以在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
谢谢
我将获得OrderProduct的每个条目,但我只是想要从我的查询集返回的那个
你只想要哪个"一个"?您的查询在Product
模型上进行过滤,因此与返回的查询集中的每个Products
关联的所有Users
, Orders
和OrderProducts
将是可访问的。
如果你想要一个特定的OrderProduct
,那么你应该过滤op = OrderProduct.objects.filter(xxxxx)
,然后像这样访问链上的模型:
op.product
, op.order
等
我建议使用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