Django在模板中使用一个模型方法(通过外键访问另一个对象)会导致多少数据库命中?

2024-05-06 23:38:13 发布

您现在位置:Python中文网/ 问答频道 /正文

特别是,调用通过外键访问另一个对象的模型方法,并在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很懒并且有一个缓存,但是我不知道它们是否适用于这种情况。在

提前谢谢!在


Tags: 方法模型selfformodelreturn产品def
1条回答
网友
1楼 · 发布于 2024-05-06 23:38:13

您可以使用预取相关的字段管理器来优化数据库访问。 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访问它

class Shipment(Model):

    discount = FloatField()

    def getProducts(self):
        return self.product_set.all()

class Product(Model):
...

现在神奇的是,我们想让django把所有的产品和货物一起拿到。在

^{pr2}$

请注意,您必须使用django1.4及更高版本。在

相关问题 更多 >