特别是,调用通过外键访问另一个对象的模型方法,并在for循环中多次调用此方法。在
我们假设以下模型为例:
class Shipment(Model):
discount = FloatField()
def getProducts(self):
return Product.objects.filter(shipment = self)
class Product(Model):
shipment = ForeignKey(Shipment)
baseCost = IntegerField()
def getDiscount(self):
return self.baseCost * self.shipment.discount
货件对每件商品都有折扣。产品模型有一种方法来计算它的折扣金额,但是要计算这个值,它必须访问它的发货量。在
(当然,我们可以将折扣作为一个字段存储在Product中,这样就不会再计算它了,但是为了这个问题,让我们忽略它)。在
现在,假设我们有以下视图:
^{pr2}$我们只需将所有货物作为上下文传递。在
最后,假设以下模板:
{% for shipment in shipments %}
{% for product in shipment.getProducts %}
{{ product.getDiscount }}
{% endfor %}
{% endfor %}
如果我对Querysets如何工作的理解是正确的,那么在第一个循环中,它会命中DB来获取所有装运(因此,到目前为止,只有1次命中)。然后在第二个循环中,它再次访问数据库以获得相应的产品,每次发货一次(so,S命中)。最后,每个产品调用它的方法,该方法通过外键访问它的发货以检索折扣,这(我假设)会导致另一次命中,每个产品一次(P次)。最后一个部分特别让我恼火,因为我们正在重新检索每一批货,我们已经在第一个for循环中做过了,但这次是一个接一个!在
总的来说,它是(1+s+(s*p))数据库命中,这似乎有点过分。在
这是正确的,还是Django以我不知道的方式优化了东西?我知道querysets很懒并且有一个缓存,但是我不知道它们是否适用于这种情况。在
提前谢谢!在
您可以使用预取相关的字段管理器来优化数据库访问。 prefetch将在后台执行一个额外的查询,并检索相关产品,从而将DB调用的总数减少到2个。在
https://docs.djangoproject.com/en/1.10/ref/models/querysets/#prefetch-related
如果您从产品对象访问了货件,则应该使用选择“相关。Select related执行对象与另一个对象的联接,并减少DB调用的次数,但它仅适用于1-1关系/1->;多个(从另一侧)。 https://docs.djangoproject.com/en/1.10/ref/models/querysets/#select-relatedhttps://docs.djangoproject.com/en/1.10/ref/models/relations/
怎么做? 考虑模型文件中的以下代码。请注意,我正在使用Django RelatedManager并使用self访问它
现在神奇的是,我们想让django把所有的产品和货物一起拿到。在
^{pr2}$请注意,您必须使用django1.4及更高版本。在
相关问题 更多 >
编程相关推荐