【问题标题】:Django prefetch_related in loop, what is wrong?循环中的Django prefetch_related,出了什么问题?
【发布时间】:2018-10-29 07:45:21
【问题描述】:

我正在尝试减少 Django 应用程序中的查询量,但不知道如何以正确的方式进行。我有一个产品模型,所有产品都有默认价格,现在我有一个客户产品,其中包含一些与客户相关的产品价格

我愿意重新设计 ;)

class Product(models.Model)
    name = models.CharField(max_length=255)
    price = models.DecimalField(default=0, max_digits=12, decimal_places=2)
    ....

    def get_prices(self, customer=None):
        '''
        get prices for the current product based on the price matrix given by bbp
        '''
        if customer:
            prices = self.get_customer_prices()
            if prices:
                self.price = self.customerproduct_set.filter(deleted=0).last().price

        return self

class CustomerProduct(AbstractProductPrice):
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)
    price = models.DecimalField(default=0, max_digits=12, decimal_places=2)
    ....

现在我想要所有具有相关客户价格的产品。

products = Product.objects.all().prefetch_related('customerproduct_set')

    for product in products:
        product.get_prices(customer=1)

预取不“工作”我不明白如何使用它..请帮助。

我的数据库中有 31 个产品,django_debug_tool 产生 35 个查询。

【问题讨论】:

  • filtercustomerproduct_set,一个简单的.prefetch_related 只能获取“.all()”可以这么说。但是,您可以构造一个 Prefetch(..) 对象,该对象可以预取过滤集。
  • 哇,我没听懂,你能给我举个例子吗? ;)
  • 但是这里有什么奇怪的地方吗?您查询.last()?但是您没有定义订单,这意味着它可以返回任何 (?) CustomerProduct 具有 deleted=0?

标签: django django-models


【解决方案1】:

仅为您感兴趣的客户预取CustomerProducts,然后使用该结果。类似的东西:

products = Product.objects.all().prefetch_related(
    models.Prefetch(
        'customerproduct_set',
        queryset=CustomerProduct.objects.filter(customer=customer, deleted=0).order_by('id')
        to_attr='customer_prices'
    )
)

def get_product_prices(product):
    customer_prices = getattr(product, 'customer_prices', None)
    if customer_prices:
        return customer_prices[-1].price
    return product.price


for product in products:
    print get_product_prices(product)

【讨论】:

  • 谢谢...我收到一个错误:分配前引用了局部变量“customer_prices”
  • 好吧,不要盲目的复制粘贴未经测试的代码,先试着理解一下吧……报错的原因是因为getattr的第二个参数没有封装成字符串,我马上就修好了。
猜你喜欢
  • 2015-01-09
  • 1970-01-01
  • 1970-01-01
  • 2014-02-15
  • 1970-01-01
  • 2012-11-30
  • 1970-01-01
  • 2012-07-28
  • 1970-01-01
相关资源
最近更新 更多